[DebianGIS-dev] r718 - in packages/thuban: . branches branches/upstream branches/upstream/current branches/upstream/current/Doc branches/upstream/current/Doc/manual branches/upstream/current/Doc/manual/images branches/upstream/current/Doc/technotes branches/upstream/current/Examples branches/upstream/current/Examples/simple_extensions branches/upstream/current/Extensions branches/upstream/current/Extensions/bboxdump branches/upstream/current/Extensions/drawshape branches/upstream/current/Extensions/export_shapefile branches/upstream/current/Extensions/gns2shp branches/upstream/current/Extensions/gns2shp/test branches/upstream/current/Extensions/importAPR branches/upstream/current/Extensions/importAPR/samples branches/upstream/current/Extensions/importAPR/test branches/upstream/current/Extensions/mouseposition branches/upstream/current/Extensions/ogr branches/upstream/current/Extensions/ogr/test branches/upstream/current/Extensions/profiling branches/upstream/current/Extensions/svgexport branches/upstream/current/Extensions/svgexport/test branches/upstream/current/Extensions/umn_mapserver branches/upstream/current/Extensions/umn_mapserver/sample branches/upstream/current/Extensions/umn_mapserver/test branches/upstream/current/Extensions/wms branches/upstream/current/Extensions/wms/test branches/upstream/current/Resources branches/upstream/current/Resources/Bitmaps branches/upstream/current/Resources/Locale branches/upstream/current/Resources/Locale/de branches/upstream/current/Resources/Locale/de/LC_MESSAGES branches/upstream/current/Resources/Locale/es branches/upstream/current/Resources/Locale/es/LC_MESSAGES branches/upstream/current/Resources/Locale/fr branches/upstream/current/Resources/Locale/fr/LC_MESSAGES branches/upstream/current/Resources/Locale/hu branches/upstream/current/Resources/Locale/hu/LC_MESSAGES branches/upstream/current/Resources/Locale/it branches/upstream/current/Resources/Locale/it/LC_MESSAGES branches/upstream/current/Resources/Locale/pt_BR branches/upstream/current/Resources/Locale/pt_BR/LC_MESSAGES branches/upstream/current/Resources/Locale/ru branches/upstream/current/Resources/Locale/ru/LC_MESSAGES branches/upstream/current/Resources/Projections branches/upstream/current/Resources/XML branches/upstream/current/Thuban branches/upstream/current/Thuban/Lib branches/upstream/current/Thuban/Model branches/upstream/current/Thuban/UI branches/upstream/current/devtools branches/upstream/current/libraries branches/upstream/current/libraries/pyprojection branches/upstream/current/libraries/pyshapelib branches/upstream/current/libraries/shapelib branches/upstream/current/libraries/thuban branches/upstream/current/po branches/upstream/current/test

Francesco Lovergine frankie at alioth.debian.org
Fri Apr 6 11:44:57 UTC 2007


Author: frankie
Date: 2007-04-06 11:44:54 +0000 (Fri, 06 Apr 2007)
New Revision: 718

Added:
   packages/thuban/branches/
   packages/thuban/branches/upstream/
   packages/thuban/branches/upstream/current/
   packages/thuban/branches/upstream/current/COPYING
   packages/thuban/branches/upstream/current/ChangeLog
   packages/thuban/branches/upstream/current/Doc/
   packages/thuban/branches/upstream/current/Doc/README
   packages/thuban/branches/upstream/current/Doc/ThubanModel.org.xmi
   packages/thuban/branches/upstream/current/Doc/ThubanModel.xmi
   packages/thuban/branches/upstream/current/Doc/manual/
   packages/thuban/branches/upstream/current/Doc/manual/Makefile
   packages/thuban/branches/upstream/current/Doc/manual/README
   packages/thuban/branches/upstream/current/Doc/manual/images/
   packages/thuban/branches/upstream/current/Doc/manual/images/1_2_legend_close.png
   packages/thuban/branches/upstream/current/Doc/manual/images/1_2_legend_dock.png
   packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.png
   packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.ps
   packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.sk
   packages/thuban/branches/upstream/current/Doc/manual/images/2_4_session_tree.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_2_fullextent.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_2_fulllayerextent.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_2_fullshapeextent.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_2_pan.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_2_zoomin.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_2_zoomout.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_3_identify.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_3_label.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_5_invisible.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_5_legend.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_5_movedown.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_5_moveup.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_5_popup_menu.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_5_props.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_5_tobottom.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_5_totop.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_5_visible.png
   packages/thuban/branches/upstream/current/Doc/manual/images/3_rename_map.png
   packages/thuban/branches/upstream/current/Doc/manual/images/4_2_layer_properties.png
   packages/thuban/branches/upstream/current/Doc/manual/images/4_2_raster_layer_properties.png
   packages/thuban/branches/upstream/current/Doc/manual/images/5_2_custom_ramp.png
   packages/thuban/branches/upstream/current/Doc/manual/images/5_2_quantiles.png
   packages/thuban/branches/upstream/current/Doc/manual/images/5_2_uniform_dist.png
   packages/thuban/branches/upstream/current/Doc/manual/images/5_2_unique_values.png
   packages/thuban/branches/upstream/current/Doc/manual/images/5_3_genclass.png
   packages/thuban/branches/upstream/current/Doc/manual/images/5_classification.png
   packages/thuban/branches/upstream/current/Doc/manual/images/6_projection.png
   packages/thuban/branches/upstream/current/Doc/manual/images/7_1_table_view.png
   packages/thuban/branches/upstream/current/Doc/manual/images/7_2_5_join.png
   packages/thuban/branches/upstream/current/Doc/manual/images/8_int_error.png
   packages/thuban/branches/upstream/current/Doc/manual/images/app_postgis_add_layer.png
   packages/thuban/branches/upstream/current/Doc/manual/images/app_postgis_db_add.png
   packages/thuban/branches/upstream/current/Doc/manual/images/app_postgis_db_management.png
   packages/thuban/branches/upstream/current/Doc/manual/mainwindow.png
   packages/thuban/branches/upstream/current/Doc/manual/mainwindow.xcf
   packages/thuban/branches/upstream/current/Doc/manual/thuban-manual-de.xml
   packages/thuban/branches/upstream/current/Doc/manual/thuban-manual.xml
   packages/thuban/branches/upstream/current/Doc/technotes/
   packages/thuban/branches/upstream/current/Doc/technotes/README
   packages/thuban/branches/upstream/current/Doc/technotes/coding_guidelines.txt
   packages/thuban/branches/upstream/current/Doc/technotes/release_process.txt
   packages/thuban/branches/upstream/current/Doc/technotes/string_representation.txt
   packages/thuban/branches/upstream/current/Examples/
   packages/thuban/branches/upstream/current/Examples/__init__.py
   packages/thuban/branches/upstream/current/Examples/simple_extensions/
   packages/thuban/branches/upstream/current/Examples/simple_extensions/README
   packages/thuban/branches/upstream/current/Examples/simple_extensions/__init__.py
   packages/thuban/branches/upstream/current/Examples/simple_extensions/hello_world.py
   packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_command.py
   packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_tool.py
   packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_tool.xpm
   packages/thuban/branches/upstream/current/Extensions/
   packages/thuban/branches/upstream/current/Extensions/__init__.py
   packages/thuban/branches/upstream/current/Extensions/bboxdump/
   packages/thuban/branches/upstream/current/Extensions/bboxdump/__init__.py
   packages/thuban/branches/upstream/current/Extensions/bboxdump/bboxdump.py
   packages/thuban/branches/upstream/current/Extensions/drawshape/
   packages/thuban/branches/upstream/current/Extensions/drawshape/README
   packages/thuban/branches/upstream/current/Extensions/drawshape/drawshape.py
   packages/thuban/branches/upstream/current/Extensions/drawshape/patch.diff
   packages/thuban/branches/upstream/current/Extensions/export_shapefile/
   packages/thuban/branches/upstream/current/Extensions/export_shapefile/__init__.py
   packages/thuban/branches/upstream/current/Extensions/export_shapefile/export_shapefile.py
   packages/thuban/branches/upstream/current/Extensions/gns2shp/
   packages/thuban/branches/upstream/current/Extensions/gns2shp/__init__.py
   packages/thuban/branches/upstream/current/Extensions/gns2shp/gns2shp.py
   packages/thuban/branches/upstream/current/Extensions/gns2shp/test/
   packages/thuban/branches/upstream/current/Extensions/gns2shp/test/README
   packages/thuban/branches/upstream/current/Extensions/gns2shp/test/__init__.py
   packages/thuban/branches/upstream/current/Extensions/gns2shp/test/ls.txt
   packages/thuban/branches/upstream/current/Extensions/gns2shp/test/test_gns2shp.py
   packages/thuban/branches/upstream/current/Extensions/importAPR/
   packages/thuban/branches/upstream/current/Extensions/importAPR/__init__.py
   packages/thuban/branches/upstream/current/Extensions/importAPR/apr.py
   packages/thuban/branches/upstream/current/Extensions/importAPR/importAPR.py
   packages/thuban/branches/upstream/current/Extensions/importAPR/odb.py
   packages/thuban/branches/upstream/current/Extensions/importAPR/samples/
   packages/thuban/branches/upstream/current/Extensions/importAPR/samples/README
   packages/thuban/branches/upstream/current/Extensions/importAPR/samples/iceland.apr
   packages/thuban/branches/upstream/current/Extensions/importAPR/test/
   packages/thuban/branches/upstream/current/Extensions/importAPR/test/README
   packages/thuban/branches/upstream/current/Extensions/importAPR/test/test_apr.py
   packages/thuban/branches/upstream/current/Extensions/mouseposition/
   packages/thuban/branches/upstream/current/Extensions/mouseposition/__init__.py
   packages/thuban/branches/upstream/current/Extensions/mouseposition/mouseposition.py
   packages/thuban/branches/upstream/current/Extensions/mouseposition/position.xpm
   packages/thuban/branches/upstream/current/Extensions/ogr/
   packages/thuban/branches/upstream/current/Extensions/ogr/__init__.py
   packages/thuban/branches/upstream/current/Extensions/ogr/ogrdialog.py
   packages/thuban/branches/upstream/current/Extensions/ogr/ogrshapes.py
   packages/thuban/branches/upstream/current/Extensions/ogr/ogrstart.py
   packages/thuban/branches/upstream/current/Extensions/ogr/test/
   packages/thuban/branches/upstream/current/Extensions/ogr/test/__init__.py
   packages/thuban/branches/upstream/current/Extensions/ogr/test/test_OGRShapestore.py
   packages/thuban/branches/upstream/current/Extensions/ogr/x.diff
   packages/thuban/branches/upstream/current/Extensions/profiling/
   packages/thuban/branches/upstream/current/Extensions/profiling/__init__.py
   packages/thuban/branches/upstream/current/Extensions/profiling/profiling.py
   packages/thuban/branches/upstream/current/Extensions/svgexport/
   packages/thuban/branches/upstream/current/Extensions/svgexport/__init__.py
   packages/thuban/branches/upstream/current/Extensions/svgexport/maplegend.py
   packages/thuban/branches/upstream/current/Extensions/svgexport/svgmapwriter.py
   packages/thuban/branches/upstream/current/Extensions/svgexport/svgsaver.py
   packages/thuban/branches/upstream/current/Extensions/svgexport/test/
   packages/thuban/branches/upstream/current/Extensions/svgexport/test/__init__.py
   packages/thuban/branches/upstream/current/Extensions/svgexport/test/test_svgmapwriter.py
   packages/thuban/branches/upstream/current/Extensions/svgexport/x.diff
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/README
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/__init__.py
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mapfile.py
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_export.py
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_handle.py
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_import.py
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/sample/
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/sample/README
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/test/
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/test/README
   packages/thuban/branches/upstream/current/Extensions/umn_mapserver/test/test_mapserver.py
   packages/thuban/branches/upstream/current/Extensions/wms/
   packages/thuban/branches/upstream/current/Extensions/wms/__init__.py
   packages/thuban/branches/upstream/current/Extensions/wms/capabilities.py
   packages/thuban/branches/upstream/current/Extensions/wms/domutils.py
   packages/thuban/branches/upstream/current/Extensions/wms/infodialog.py
   packages/thuban/branches/upstream/current/Extensions/wms/layer.py
   packages/thuban/branches/upstream/current/Extensions/wms/parser.py
   packages/thuban/branches/upstream/current/Extensions/wms/properties.py
   packages/thuban/branches/upstream/current/Extensions/wms/test/
   packages/thuban/branches/upstream/current/Extensions/wms/test/adjustpath.py
   packages/thuban/branches/upstream/current/Extensions/wms/test/test_domutils.py
   packages/thuban/branches/upstream/current/Extensions/wms/test/test_ogclib.py
   packages/thuban/branches/upstream/current/Extensions/wms/test/test_parser.py
   packages/thuban/branches/upstream/current/Extensions/wms/wms.py
   packages/thuban/branches/upstream/current/MANIFEST.in
   packages/thuban/branches/upstream/current/NEWS
   packages/thuban/branches/upstream/current/PKG-INFO
   packages/thuban/branches/upstream/current/README
   packages/thuban/branches/upstream/current/Resources/
   packages/thuban/branches/upstream/current/Resources/Bitmaps/
   packages/thuban/branches/upstream/current/Resources/Bitmaps/bottom_layer.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/close_12.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/dock_12.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/fullextent.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/fulllayerextent.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/fullselextent.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_all.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_none.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_not.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/hide_layer.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/identify.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/label.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/layer_properties.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/legend_icon_layer.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/legend_icon_map.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/lower_layer.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/pan.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/raise_layer.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/show_layer.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/top_layer.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/undock_12.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/zoom_in.xpm
   packages/thuban/branches/upstream/current/Resources/Bitmaps/zoom_out.xpm
   packages/thuban/branches/upstream/current/Resources/Locale/
   packages/thuban/branches/upstream/current/Resources/Locale/de/
   packages/thuban/branches/upstream/current/Resources/Locale/de/LC_MESSAGES/
   packages/thuban/branches/upstream/current/Resources/Locale/de/LC_MESSAGES/thuban.mo
   packages/thuban/branches/upstream/current/Resources/Locale/es/
   packages/thuban/branches/upstream/current/Resources/Locale/es/LC_MESSAGES/
   packages/thuban/branches/upstream/current/Resources/Locale/es/LC_MESSAGES/thuban.mo
   packages/thuban/branches/upstream/current/Resources/Locale/fr/
   packages/thuban/branches/upstream/current/Resources/Locale/fr/LC_MESSAGES/
   packages/thuban/branches/upstream/current/Resources/Locale/fr/LC_MESSAGES/thuban.mo
   packages/thuban/branches/upstream/current/Resources/Locale/hu/
   packages/thuban/branches/upstream/current/Resources/Locale/hu/LC_MESSAGES/
   packages/thuban/branches/upstream/current/Resources/Locale/hu/LC_MESSAGES/thuban.mo
   packages/thuban/branches/upstream/current/Resources/Locale/it/
   packages/thuban/branches/upstream/current/Resources/Locale/it/LC_MESSAGES/
   packages/thuban/branches/upstream/current/Resources/Locale/it/LC_MESSAGES/thuban.mo
   packages/thuban/branches/upstream/current/Resources/Locale/pt_BR/
   packages/thuban/branches/upstream/current/Resources/Locale/pt_BR/LC_MESSAGES/
   packages/thuban/branches/upstream/current/Resources/Locale/pt_BR/LC_MESSAGES/thuban.mo
   packages/thuban/branches/upstream/current/Resources/Locale/ru/
   packages/thuban/branches/upstream/current/Resources/Locale/ru/LC_MESSAGES/
   packages/thuban/branches/upstream/current/Resources/Locale/ru/LC_MESSAGES/thuban.mo
   packages/thuban/branches/upstream/current/Resources/Projections/
   packages/thuban/branches/upstream/current/Resources/Projections/defaults.proj
   packages/thuban/branches/upstream/current/Resources/Projections/epsg-deprecated.proj
   packages/thuban/branches/upstream/current/Resources/Projections/epsg.proj
   packages/thuban/branches/upstream/current/Resources/XML/
   packages/thuban/branches/upstream/current/Resources/XML/projfile.dtd
   packages/thuban/branches/upstream/current/Resources/XML/thuban-0.8.dtd
   packages/thuban/branches/upstream/current/Resources/XML/thuban-0.9.dtd
   packages/thuban/branches/upstream/current/Resources/XML/thuban-1.0.dtd
   packages/thuban/branches/upstream/current/Resources/XML/thuban-1.1.dtd
   packages/thuban/branches/upstream/current/Resources/XML/thuban.dtd
   packages/thuban/branches/upstream/current/Thuban/
   packages/thuban/branches/upstream/current/Thuban/Lib/
   packages/thuban/branches/upstream/current/Thuban/Lib/__init__.py
   packages/thuban/branches/upstream/current/Thuban/Lib/classmapper.py
   packages/thuban/branches/upstream/current/Thuban/Lib/connector.py
   packages/thuban/branches/upstream/current/Thuban/Lib/fileutil.py
   packages/thuban/branches/upstream/current/Thuban/Lib/version.py
   packages/thuban/branches/upstream/current/Thuban/Model/
   packages/thuban/branches/upstream/current/Thuban/Model/__init__.py
   packages/thuban/branches/upstream/current/Thuban/Model/base.py
   packages/thuban/branches/upstream/current/Thuban/Model/classgen.py
   packages/thuban/branches/upstream/current/Thuban/Model/classification.py
   packages/thuban/branches/upstream/current/Thuban/Model/color.py
   packages/thuban/branches/upstream/current/Thuban/Model/data.py
   packages/thuban/branches/upstream/current/Thuban/Model/extension.py
   packages/thuban/branches/upstream/current/Thuban/Model/label.py
   packages/thuban/branches/upstream/current/Thuban/Model/layer.py
   packages/thuban/branches/upstream/current/Thuban/Model/load.py
   packages/thuban/branches/upstream/current/Thuban/Model/map.py
   packages/thuban/branches/upstream/current/Thuban/Model/messages.py
   packages/thuban/branches/upstream/current/Thuban/Model/postgisdb.py
   packages/thuban/branches/upstream/current/Thuban/Model/proj.py
   packages/thuban/branches/upstream/current/Thuban/Model/range.py
   packages/thuban/branches/upstream/current/Thuban/Model/resource.py
   packages/thuban/branches/upstream/current/Thuban/Model/save.py
   packages/thuban/branches/upstream/current/Thuban/Model/scalebar.py
   packages/thuban/branches/upstream/current/Thuban/Model/session.py
   packages/thuban/branches/upstream/current/Thuban/Model/table.py
   packages/thuban/branches/upstream/current/Thuban/Model/transientdb.py
   packages/thuban/branches/upstream/current/Thuban/Model/wellknowntext.py
   packages/thuban/branches/upstream/current/Thuban/Model/xmlreader.py
   packages/thuban/branches/upstream/current/Thuban/Model/xmlwriter.py
   packages/thuban/branches/upstream/current/Thuban/UI/
   packages/thuban/branches/upstream/current/Thuban/UI/__init__.py
   packages/thuban/branches/upstream/current/Thuban/UI/about.py
   packages/thuban/branches/upstream/current/Thuban/UI/altpathdialog.py
   packages/thuban/branches/upstream/current/Thuban/UI/application.py
   packages/thuban/branches/upstream/current/Thuban/UI/baserenderer.py
   packages/thuban/branches/upstream/current/Thuban/UI/classgen.py
   packages/thuban/branches/upstream/current/Thuban/UI/classifier.py
   packages/thuban/branches/upstream/current/Thuban/UI/colordialog.py
   packages/thuban/branches/upstream/current/Thuban/UI/command.py
   packages/thuban/branches/upstream/current/Thuban/UI/common.py
   packages/thuban/branches/upstream/current/Thuban/UI/context.py
   packages/thuban/branches/upstream/current/Thuban/UI/controls.py
   packages/thuban/branches/upstream/current/Thuban/UI/dbdialog.py
   packages/thuban/branches/upstream/current/Thuban/UI/dialogs.py
   packages/thuban/branches/upstream/current/Thuban/UI/dock.py
   packages/thuban/branches/upstream/current/Thuban/UI/exceptiondialog.py
   packages/thuban/branches/upstream/current/Thuban/UI/extensionregistry.py
   packages/thuban/branches/upstream/current/Thuban/UI/hittest.py
   packages/thuban/branches/upstream/current/Thuban/UI/identifyview.py
   packages/thuban/branches/upstream/current/Thuban/UI/join.py
   packages/thuban/branches/upstream/current/Thuban/UI/labeldialog.py
   packages/thuban/branches/upstream/current/Thuban/UI/layerproperties.py
   packages/thuban/branches/upstream/current/Thuban/UI/legend.py
   packages/thuban/branches/upstream/current/Thuban/UI/main.py
   packages/thuban/branches/upstream/current/Thuban/UI/mainwindow.py
   packages/thuban/branches/upstream/current/Thuban/UI/menu.py
   packages/thuban/branches/upstream/current/Thuban/UI/messages.py
   packages/thuban/branches/upstream/current/Thuban/UI/multiplechoicedialog.py
   packages/thuban/branches/upstream/current/Thuban/UI/projdialog.py
   packages/thuban/branches/upstream/current/Thuban/UI/projlist.py
   packages/thuban/branches/upstream/current/Thuban/UI/rasterlayerproperties.py
   packages/thuban/branches/upstream/current/Thuban/UI/renderer.py
   packages/thuban/branches/upstream/current/Thuban/UI/resource.py
   packages/thuban/branches/upstream/current/Thuban/UI/scalebar.py
   packages/thuban/branches/upstream/current/Thuban/UI/selection.py
   packages/thuban/branches/upstream/current/Thuban/UI/sizers.py
   packages/thuban/branches/upstream/current/Thuban/UI/tableview.py
   packages/thuban/branches/upstream/current/Thuban/UI/tree.py
   packages/thuban/branches/upstream/current/Thuban/UI/view.py
   packages/thuban/branches/upstream/current/Thuban/UI/viewport.py
   packages/thuban/branches/upstream/current/Thuban/__init__.py
   packages/thuban/branches/upstream/current/Thuban/version.py
   packages/thuban/branches/upstream/current/devtools/
   packages/thuban/branches/upstream/current/devtools/create_epsg.py
   packages/thuban/branches/upstream/current/libraries/
   packages/thuban/branches/upstream/current/libraries/pyprojection/
   packages/thuban/branches/upstream/current/libraries/pyprojection/LICENSE
   packages/thuban/branches/upstream/current/libraries/pyprojection/MANIFEST.in
   packages/thuban/branches/upstream/current/libraries/pyprojection/Projection.i
   packages/thuban/branches/upstream/current/libraries/pyprojection/Projection.py
   packages/thuban/branches/upstream/current/libraries/pyprojection/Projection_wrap.c
   packages/thuban/branches/upstream/current/libraries/pyprojection/setup.py
   packages/thuban/branches/upstream/current/libraries/pyprojection/swighelp.txt
   packages/thuban/branches/upstream/current/libraries/pyshapelib/
   packages/thuban/branches/upstream/current/libraries/pyshapelib/COPYING
   packages/thuban/branches/upstream/current/libraries/pyshapelib/ChangeLog
   packages/thuban/branches/upstream/current/libraries/pyshapelib/MANIFEST.in
   packages/thuban/branches/upstream/current/libraries/pyshapelib/NEWS
   packages/thuban/branches/upstream/current/libraries/pyshapelib/README
   packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib.i
   packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib.py
   packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib_wrap.c
   packages/thuban/branches/upstream/current/libraries/pyshapelib/pyshapelib_api.h
   packages/thuban/branches/upstream/current/libraries/pyshapelib/pytest.py
   packages/thuban/branches/upstream/current/libraries/pyshapelib/setup.py
   packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib.i
   packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib.py
   packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib_wrap.c
   packages/thuban/branches/upstream/current/libraries/pyshapelib/shptreemodule.c
   packages/thuban/branches/upstream/current/libraries/pyshapelib/testdbf.py
   packages/thuban/branches/upstream/current/libraries/shapelib/
   packages/thuban/branches/upstream/current/libraries/shapelib/dbfopen.c
   packages/thuban/branches/upstream/current/libraries/shapelib/shapefil.h
   packages/thuban/branches/upstream/current/libraries/shapelib/shpopen.c
   packages/thuban/branches/upstream/current/libraries/shapelib/shptree.c
   packages/thuban/branches/upstream/current/libraries/thuban/
   packages/thuban/branches/upstream/current/libraries/thuban/gdalwarp.cpp
   packages/thuban/branches/upstream/current/libraries/thuban/swigPtrConvertHack.h
   packages/thuban/branches/upstream/current/libraries/thuban/wxPython_int.h
   packages/thuban/branches/upstream/current/libraries/thuban/wxproj.cpp
   packages/thuban/branches/upstream/current/po/
   packages/thuban/branches/upstream/current/po/Makefile
   packages/thuban/branches/upstream/current/po/README
   packages/thuban/branches/upstream/current/po/de.po
   packages/thuban/branches/upstream/current/po/es.po
   packages/thuban/branches/upstream/current/po/fr.po
   packages/thuban/branches/upstream/current/po/hu.po
   packages/thuban/branches/upstream/current/po/it.po
   packages/thuban/branches/upstream/current/po/pt_BR.po
   packages/thuban/branches/upstream/current/po/ru.po
   packages/thuban/branches/upstream/current/po/thuban.pot
   packages/thuban/branches/upstream/current/setup.cfg
   packages/thuban/branches/upstream/current/setup.py
   packages/thuban/branches/upstream/current/test/
   packages/thuban/branches/upstream/current/test/README
   packages/thuban/branches/upstream/current/test/localessupport.py
   packages/thuban/branches/upstream/current/test/mockgeo.py
   packages/thuban/branches/upstream/current/test/postgissupport.py
   packages/thuban/branches/upstream/current/test/runtests.py
   packages/thuban/branches/upstream/current/test/support.py
   packages/thuban/branches/upstream/current/test/test_base.py
   packages/thuban/branches/upstream/current/test/test_baserenderer.py
   packages/thuban/branches/upstream/current/test/test_classgen.py
   packages/thuban/branches/upstream/current/test/test_classification.py
   packages/thuban/branches/upstream/current/test/test_classmapper.py
   packages/thuban/branches/upstream/current/test/test_color.py
   packages/thuban/branches/upstream/current/test/test_command.py
   packages/thuban/branches/upstream/current/test/test_connector.py
   packages/thuban/branches/upstream/current/test/test_csv_table.py
   packages/thuban/branches/upstream/current/test/test_dbf_table.py
   packages/thuban/branches/upstream/current/test/test_derivedshapestore.py
   packages/thuban/branches/upstream/current/test/test_export.py
   packages/thuban/branches/upstream/current/test/test_fileutil.py
   packages/thuban/branches/upstream/current/test/test_hittest.py
   packages/thuban/branches/upstream/current/test/test_label.py
   packages/thuban/branches/upstream/current/test/test_layer.py
   packages/thuban/branches/upstream/current/test/test_lib_version.py
   packages/thuban/branches/upstream/current/test/test_load.py
   packages/thuban/branches/upstream/current/test/test_load_0_2.py
   packages/thuban/branches/upstream/current/test/test_load_0_8.py
   packages/thuban/branches/upstream/current/test/test_load_0_9.py
   packages/thuban/branches/upstream/current/test/test_load_1_0.py
   packages/thuban/branches/upstream/current/test/test_map.py
   packages/thuban/branches/upstream/current/test/test_memory_table.py
   packages/thuban/branches/upstream/current/test/test_menu.py
   packages/thuban/branches/upstream/current/test/test_mockgeo.py
   packages/thuban/branches/upstream/current/test/test_postgis_db.py
   packages/thuban/branches/upstream/current/test/test_postgis_session.py
   packages/thuban/branches/upstream/current/test/test_proj.py
   packages/thuban/branches/upstream/current/test/test_range.py
   packages/thuban/branches/upstream/current/test/test_save.py
   packages/thuban/branches/upstream/current/test/test_scalebar.py
   packages/thuban/branches/upstream/current/test/test_selection.py
   packages/thuban/branches/upstream/current/test/test_session.py
   packages/thuban/branches/upstream/current/test/test_shapefilestore.py
   packages/thuban/branches/upstream/current/test/test_stringrepresentation.py
   packages/thuban/branches/upstream/current/test/test_transientdb.py
   packages/thuban/branches/upstream/current/test/test_viewport.py
   packages/thuban/branches/upstream/current/test/test_wellknowntext.py
   packages/thuban/branches/upstream/current/test/test_wxproj.py
   packages/thuban/branches/upstream/current/test/test_xmlsupport.py
   packages/thuban/branches/upstream/current/test/xmlsupport.py
   packages/thuban/branches/upstream/current/thuban.py
   packages/thuban/tags/
Log:
[svn-inject] Installing original source of thuban

Added: packages/thuban/branches/upstream/current/COPYING
===================================================================
--- packages/thuban/branches/upstream/current/COPYING	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/COPYING	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.

Added: packages/thuban/branches/upstream/current/ChangeLog
===================================================================
--- packages/thuban/branches/upstream/current/ChangeLog	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/ChangeLog	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,12521 @@
+2007-03-13  Bernhard Reiter <bernhard at intevation.de>
+
+	More release preparations: Translation string updated.  Release date 
+	added.
+
+	* po/*: Updated .po files with new strings. 
+
+	* po/de.po: Completed German translation (3 missing, one fuzzy).
+
+	* README: Bumped minium requirement of pysqlite to 1.0.1 (as I believe
+	Thuban was tested with on Debian.)
+
+	* NEWS: New phrasing for "changes up to". Added release date.
+
+	*  Thuban/UI/about.py: Added fileencoding information, otherwise
+	xgettext from 0.16.1 did not want to run on this file.
+
+	* Thuban/UI/__init__.py: Calling wx.Locale() with with parameter
+	wx.LANGUAGE_DEFAULT now. Without this change no message catalog is
+	loaded in wxPython 2.6.3.2.1.5 and thus the translation would not work. 
+
+	* setup.cfg: Change tarball compression from gzip to bzip2.
+
+	* packaging/debian: Moved the directory in here from toplevel,
+	because there could be several debian packaging dirs and this
+	is outdated.
+
+	* MANIFEST.in: Added toplevel ChangeLog to distribution.
+	Made sure that files under packaging are actually packaged.
+
+2007-02-26 Bernhard Reiter <bernhard at intevation.de>
+
+	* MANIFEST.in: Added *.xmi to Doc so that ThubanModel.xmi is included.
+
+	* Extensions/svgexport/TODO: Added findings about how to write raster
+	in SVG.
+
+	* Extensions/svgexport/svgmapwriter.py: untabified two lines. 
+	Fixed a typo.
+
+	* Doc/ThubanModel.xmi: Updated the format of the umbrello file.
+	Loaded and saved with umbrello 1.3.2, manually changed the
+	codegeneration tag to be empty again and change the XMI.model
+	to not contain a local path.
+	Now umbrello 1.5.5 also opens the file without crashing. 
+	Thanks to Philippe LeGrand who discovered the problem and the
+	solution and filed report 141279 on bugs.kde.org for this umbrello
+	problem.
+
+2007-02-21 Didrik Pinte <dpinte at itae.be>
+
+	* Extensions/umn_mapserver/__init__.py : UTF8 locales bugfix
+
+2007-02-20 Bernhard Reiter <bernhard at intevation.de>
+
+	* Thuban/version.py, setup.py: Getting ready for release 1.2.0.
+	Using this version number.
+
+	* Doc/README: fixed a typo.
+
+	* Doc/technotes/release_process.txt: Updated. Reference platform
+	is Debian Etch now. If windows, it should be window XP.
+	Marked a few entries in the instructions as "Old:".
+
+	* README: Bumped requirements to wxWidgets 2.6.3.2 and gdal 1.3.2.. 
+	Added urls for homepage and infrastructure on wald. Fixed a typo.
+
+	* MANIFEST.in: Added subdir "packaging" which should be in the tarball.
+
+	* NEWS: Completed changes from 1.1.0 until today as gathered from
+	the Changelog entries. Added small section about OGR known problems
+	because we do not have a release-notes file so far.
+
+	* Doc/manual/thuban-manual.xml: Removed the installation instructions
+	as they are outdated and they should be only in one place.
+	Bumped version number of the document to 1.2.0. Marked it as Draft
+	in the title.
+
+	* Extensions/svgexport/: Get ready for release. Bump version
+	number to 1.0.1. Adjusted numbers in TODO.
+
+	* Thuban/UI/about.py: Reworked the about text. It shows now
+	when somebody was active on Thuban. Added a list of maintainers.
+	Bernhard Reiter is the current maintainer, following up on Bernhard
+	Herzog. 
+
+	* Extensions/export_shapefile/export_shapefile.py: untabify.
+
+	* test/README: Added example how to set the PATH for postgis on
+	Debian Etch.
+
+2007-01-13 Didrik Pinte <dpinte at itae.be>
+
+	bboxdump, gns2shp, importAPR, mouseposition, ogr, profiling, svgexport
+	extensions migrated to wxPython 2.6
+
+	* Extensions/bboxdump/bboxdump.py: 
+	updated wx statements
+
+	* Extensions/gns2shp/gns2shp.py: 
+	updated wx statements
+
+	* Extensions/importAPR/importAPR.py:
+	updated wx statements
+
+	* Extensions/mouseposition/mouseposition.py:
+	updated wx statements
+
+	* Extensions/ogr/
+	ogrdialog.py, ogrstart.py:
+	updated wx statements
+
+	* Extensions/profiling/profiling.py:
+	updated wx statements
+
+	* Extensions/svgexport/
+	maplegend.py, svgsaver.py:
+	updated wx statements
+
+
+2007-01-08 Didrik Pinte <dpinte at itae.be>
+	
+	export_shapefile extension migrated to wxPython 2.6
+
+	* Extensions/export_shapefile/export_shapefile.py: 
+	updated wx statements, changed the FileDialog to wx.SAVE (was wx.OPEN)
+
+2007-01-08 Didrik Pinte <dpinte at itae.be>
+	
+	umn_mapserver extension migrated to wxPython 2.6
+
+	* Extensions/umn_maserver/
+	mf_handle.py, mf_import.py, mf_export.py: 
+	update wx imports to 2.6 policy
+
+2007-01-06 Didrik Pinte <dpinte at itae.be>
+
+	UTF-8 locales support reading non utf-8 files. 
+	This is a workaround and not a real bugfix. See 
+	http://wald.intevation.org/tracker/index.php?func=detail&aid=118 
+	for more details
+
+	* Thuban/UI/tableview.py, controls.py, baserenderer.py, view.py: 
+	decode text from iso-8859-1 encoding.
+
+2007-01-01 Bernhard Reiter <bernhard at intevation.de>
+
+	* test/postgissupport.py, test/test_postgis_db.py: adding an 
+	explicit WITH OIDS to the create table commands. This fixes tests
+	that rely on an oid column to be present for postgresql >=8.0.
+	Thanks for Frank Koormann for the hint.
+
+2006-11-06 Didrik Pinte <dpinte at itae.be>
+
+	* libraries/thuban/wxproj.cpp: bugfix - allow compilation with
+	msvc++ toolkit 2003
+
+2006-11-06 Bernhard Reiter <bernhard at intevation.de>
+
+	Made it easier to run PostGIS test on Debian Etch. Improving
+	https://wald.intevation.org/tracker/index.php?func=detail&aid=173 .
+
+	* test/postgissupport.py: Taking pg_ctl and initdb commands
+	from internal variables now. Adding deactivated example values
+	for Debian Etch.  
+	find_postgis_sql(): Added special line for Debian Etch postgresql-8.1.
+	Added copyright year 2006.
+
+2006-10-25 Bernhard Reiter <bernhard at intevation.de>
+	
+	Moved ogr Extension to Extension menu.
+
+	* Extensions/ogr/
+	__init__.py, ogrstart.py, ogrshapes.py, ogrdialog.py
+	test/test_OGRShapestore.py, test/__init__.py: 
+	adding encoding information and made sure Autor's names 
+	with an umlaut are actually written with an umlaut.
+
+	* Extensions/ogr/ogrstrat.py: now registering in menu "Extensions",
+	having a "(testing)" string before the submenu to prepare for 1.2.0
+	release.  Bumped copyright year to 2006.
+
+2006-10-15 Bernhard Reiter <bernhard at intevation.de>
+
+	* Thuban/UI/renderer.py: Added module variable verbose and
+	added verbose output before doing a raster projection.
+	Minor: Added (c) year 2006.
+
+	* test/test_baserenderer.py: Added new function
+	test_projected_raster_decimalcommalocale()
+	Added new author Bernhard Reiter and new copyright year 2006.
+
+	* libraries/thuban/gdalwarp.cpp(ProjectRasterFile): Adding
+	switching to LC_NUMERIC "C" and back before calling GDAL functions -
+	only #if python >=2.4 .
+
+2006-10-10 Didrik Pinte <dpinte at itae.be>
+
+	Win32 build updates 
+
+	* setup.py : 
+	    - update to the latest libs for win32 setup tasks
+		- added gdal and Lib content to the inno setup build task
+		- added stable and experimental extensions to setup packages
+
+	* thuban.py :
+		- gdal support for win32 inno installation
+
+2006-10-10 Didrik Pinte <dpinte at itae.be>
+
+	* Thuban/Model/layer.py (Layer.GetLabelPosFromShape): new method 
+	extracted from Thuban/UI/viewport.py
+	* Thuban/UI/viewport.py (Viewport.LabelShapeAt): uses new method
+
+2006-09-28 Didrik Pinte <dpinte at itae.be>
+
+	* Thuban/UI/classgen.py: bugfix due to wx2.6 update
+
+	* Thuban/UI/view.py: removed non needed declaration
+
+	* Thuban/UI/selection.py : typo correction
+
+2006-09-24 Bernhard Reiter <bernhard at intevation.de>
+
+	* Thuban/Model/proj.py(_do_we_have_to_work_around_broken_proj): 
+	Making the test more robust for observed python 2.3 problems
+	with setlocale().
+
+	* test/runtests.py: Added new option ---setdecimalcommalocale
+	to run all tests with an LC_NUMERIC that uses comma as decimal_point.
+	Minor: Added (c) year 2006. Fixed typo in a docstring.
+
+	* test/test_transientdb.py: Minor: Added (c) year 2006. Fixed typo in
+	a docstring.
+
+2006-09-23 Bernhard Reiter <bernhard at intevation.de>
+
+	* Extensions/ogr/test/test_OGRShapestore.py: fixed skip_if_no_ogr()
+	and added it to TestOGRTable.setUp() so that all tests get skipped
+	if ogr cannot be imported. Added (c) year 2006.
+
+2006-09-18 Didrik Pinte <dpinte at itae.be>
+	
+	* wxPython 2.6 update : wx 2.4 syntax has been updated to 2.6
+	
+2006-09-18 Bernhard Reiter <bernhard at intevation.de>
+
+	Fixed proj behaviour with python >=2.4 when decimal_point != '.'.
+
+	* Thuban/UI/application.py: Fixed warning dialog when gdal is missing.
+
+	* test/test_proj.py: new test_lc_numeric_robustness(). Added author
+	Bernhard Reiter and new copyright year 2006.
+
+	* Thuban/Model/proj.py: New _do_we_have_to_work_around_broken_proj()
+	and Projection.assuregoodlocale(), Projection.assureinitlocale().
+	Added author Bernhard Reiter and (c) 2006.
+
+2006-09-15 Bernhard Reiter <bernhard at intevation.de>
+
+	* README: added RXP and pyRXP as optional for tests.
+
+	* test/localessupport.py: New. Contains a helper function
+	to find a locale with comma used as decimal_point.
+
+2006-08-31 Bernhard Reiter <bernhard at intevation.de>
+
+	* README: fixed URLs to sqlite and pysqlite.
+
+	* Thuban/UI/about.py: Added Didrik Pinte as contributor. Extended
+	  copyright range to include 2006.
+
+2006-06-29 Didrik Pinte <dpinte at itae.be>
+
+	* Thuban/UI/main.py: circular import fix.
+
+2006-06-27 Frank Koormann <frank at intevation.de>
+
+	New Classification "Pattern": Classify text attributes by regexp.
+
+	* Thuban/Model/classification.py (class ClassGroupPattern): 
+	New, group is associated with a regular expression.
+	(Classification._compile_classification): Store compiled regexp and
+	original group for pattern.
+	(Classification.FindGroup): Added pattern.
+
+	* Thuban/UI/classifier.py 
+	(ClassGrid._OnLabelRightClicked, ClassGrid.labelPopup): 
+	New, add popup to select singleton/pattern.
+	(ClassTable.GetRowLabelValue, ClassTable.GetValueAsCustom,
+	ClassTable.SetValueAsCustom): Added pattern.
+	(ClassTable.__ParseInput): Autodetect singleton/pattern.
+
+	* Thuban/Model/save.py (SessionSaver.write_classification): 
+	Added pattern.
+
+	* Thuban/Model/load.py (SessionLoader.start_clpattern,
+	SessionLoader.end_clpattern): New, process pattern elements.
+
+	* test/test_classification.py (class TestClassGroupPattern): New.
+	(TestClassification.test_add_pattern, 
+	TestClassification.test_multiple_groups_textual,
+	TestClassification.test_deepcopy_textual): New.
+	(TestClassification.test_multiple_groups_numerical): 
+	Renamed test_multiple_groups.
+	(TestClassification.test_deepcopy_numerical): Renamed test_deepcopy.
+
+	* test/test_save.py (SaveSessionTest.testClassifiedLayer): 
+	Added pattern.
+
+	* test/test_load.py (ClassificationTest.TestLayers, TestClassification):
+	Added pattern.
+
+	* test/test_layer.py 
+	(TestLayerModification.test_set_classification_textual): New
+	(TestLayerModification.test_set_classification_numerical):
+	Renamed test_set_classification.
+
+	* Doc/manual/thuban-manual.xml: Added pattern to layer classification
+	description.
+
+	* Resources/XML/thuban-1.1.dtd: Added clpattern element and attribs.
+
+2006-06-29 Didrik Pinte <dpinte at itae.be>
+
+	* Thuban/version.py: Bugfix determination of SQLite, the wright one !
+	  
+2006-06-28 Didrik Pinte <dpinte at itae.be>
+
+	* packaging/windows/thubanstart.py: sample file loading all the stable
+	extensions
+	
+2006-06-28 Didrik Pinte <dpinte at itae.be>
+
+	* Thuban/version.py: Bugfix determination of SQLite on old and recent
+	systems (support pysqlite1 and pysqlite2)
+
+2006-06-27 Frank Koormann <frank at intevation.de>
+
+	* Thuban/version.py: Bugfix determination of SQLite on old systems.
+
+2006-05-17 Didrik Pinte <dpinte at itae.be>
+	* Extensions/ogr/__init__.py : updated test for win32 and correct
+	imports
+
+2006-05-15 Didrik Pinte <dpinte at itae.be>
+	Ashamed ... still some tabs in the files
+
+	* Thuban/version.py : tabs removed	
+	* Thuban/Model/transientdb.py : tabs removed
+
+2006-05-15 Didrik Pinte <dpinte at itae.be>
+
+	* Thuban/version.py : coding style correction	
+	* Thuban/Model/transientdb.py : coding style correction
+
+2006-05-15 Didrik Pinte <dpinte at itae.be>
+
+	* Thuban/version.py : Updated imports to support pysqlite2
+
+	* Thuban/Model/transientdb.py : Updated imports to support pysqlite2
+	Patched the querying system to support the param style of pysqlite2
+
+2006-04-24 Didrik Pinte <dpinte at itae.be>
+
+	* Extensions/svgexport/__init__.py: The extension now works on win32
+	architecture. Bug #87 corrected.
+
+2006-04-20 Bernhard Reiter <bernhard at intevation.de>
+
+	* Doc/technotes/coding_guidelines.txt: Changed text from CVS to SVN.
+	Removed emacs specific hint and replaced it with a general hint
+	that editors might support writing changelogs.
+
+2006-04-12 Bernhard Reiter <bernhard at intevation.de>
+
+	* Thuban/version.py: Changed thuban_release mechanism to use "svn"
+	instead of "cvs".
+
+2006-03-31  Bernhard Reiter <bernhard at intevation.de>
+
+	* libraries/thuban/wxproj.cpp: including proj_api.h instead of
+	projects.h now. According the Frank Warmerdam and man pj_init
+	this is the public interface to proj. Thus I have changed PJ to projPJ.
+	And I could remove the hack to avoid clashes with typedef PVALUE
+	and #define LP in projects.h clashing with symbols when trying to 
+	build on windows. The file is cleaner and nicer now.
+
+2006-03-29  Bernhard Reiter <bernhard at intevation.de>
+
+	* libraries/thuban/wxproj.cpp: undef LP to avoid clash when 
+	trying to build with mingw.
+
+2005-10-18  Bernhard Reiter <bernhard at intevation.de>
+
+	* Thuban/UI/about.py: remove unused import of getdefaultlocale.
+	Added display of internal encoding to the about dialog text.
+
+	* Extensions/svgexport/__init__.py: changed version to "1.0.0+cvs".
+
+2005-10-18  Bernhard Reiter <bernhard at intevation.de>
+
+	Startup improved: We fail right away if the internal encoding could
+	not be determined.
+
+	* Thuban/__init__.py (get_internal_encoding): new.
+
+	* test/test_stringrepresentation.py (class TestInternalEncoding): 
+	Preserve the internal encoding for the tests in this class.
+
+2005-10-17  Bernhard Reiter <bernhard at intevation.de>
+
+	* test/test_stringrepresentation.py: New file, for now testing
+	that set_internal_coding() is throwing an exception for bad exceptions.
+
+	* Thuban/__init__.py (set_internal_encoding): added a forwards
+	and backward translation, so that we fail early if the 
+	internal_encoding is bad.
+
+2005-10-17  Bernhard Reiter <bernhard at intevation.de>
+
+	svgexport 1.0.0cvs: Fixed ARC layer writing: No filling is done.
+	You could actually get polylines with filling in between,
+	when the classification for the lines had a fill color.
+	E.g. this happens when you generate a classification from a ramp.
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	New test_export_arc_no_fill(). Extend copyright notice to 2005.
+
+	* Extensions/svgexport/svgmapwriter.py
+	(SVGRenderer.draw_shape_layer_incrementally()):
+	Setting TRANSPARENT_BRUSH for shaptype ARC. 
+	Extend copyright notice to 2005.
+
+	* Extensions/svgexport/__init__.py: Extend copyright notice to 2005.
+
+2005-09-08  Frank Koormann <frank at intevation.de>
+
+	* Doc/manual/thuban-manual.xml (Map Management): Fixed typo reported 
+	by Erik (sigra.at.home.se)
+
+2005-08-18  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/renderer.py (ScreenRenderer.draw_selection_incrementally): 
+	Call the right method for the default size.
+
+2005-08-11  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Extensions/export_shapefile: New.
+
+	* Extensions/export_shapefile/__init__.py: New. Initialize
+	the export_shapefile extension.
+
+	* Extensions/export_shapefile/export_shapefile.py: New.
+	Exports a layer as a Shapefile.
+
+2005-08-08  Jan-Oliver Wagner <jan at intevation.de>
+
+	* po/de.po: String fixes. This fixes Debian bug #313843.
+
+2005-07-27  Jan-Oliver Wagner <jan at intevation.de>
+
+	Remove the attributes from the layer element in
+	.thuban files for the save routine.
+	This also solves RT bug #3149,
+	https://intevation.de/rt/webrt?serial_num=3149
+
+	* test/test_load.py: (TestSingleLayer, TestNonAsciiColumnName,
+	TestLayerVisibility, TestSymbolSize, TestClassification, TestLabels,
+	TestLayerProjection, TestJoinedTable, TestLabelLayer): Removed
+	attributes from layer element to classification clnull element.
+
+	* test/test_save.py (SaveSessionTest.testSingleLayer,
+	SaveSessionTest.testLayerProjection,
+	SaveSessionTest.testClassifiedLayer,
+	SaveSessionTest.test_joined_table, SaveSessionTest.test_save_postgis):
+	Removed attributes from layer element to classification clnull element.
+	(test_save_postgis.NonConnectionStore._fetch_table_information):
+	added pretending to have a shape_type.
+
+	* Resources/XML/thuban-1.1.dtd: Make the attributes field
+	and field_type of classification optional.
+
+	* Thuban/Model/classification.py (Classification.TreeItem.build_info):
+	Added output of size.
+
+	* Thuban/Model/load.py (SessionLoader.start_classification):
+	Change attribute 'field' and 'field_type' from obligatory to
+	optional to allow empty classes (ie.  only with a default=clnull).
+
+	* Thuban/Model/save.py (SessionSaver.write_layer): Don't write
+	any attributes anymore for the layer element.
+	(SessionSaver.write_classification): Even if there is no
+	classification field, still write the classification because
+	the clnull (default) symbol will not be defined anymore as
+	part of the layer element.
+
+2005-07-05  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (setup call): Version 1.1.0
+
+	* NEWS: Update for 1.1.0
+
+	* MANIFEST.in: Add *.txt to files taken from Doc.  Otherwise the
+	technores won't be included
+
+	* Thuban/UI/about.py (About.__init__): Extend copyright notice to
+	2005
+
+	* po/de.po: Updated.
+
+2005-07-05  Bernhard Herzog  <bh at intevation.de>
+
+	* README: gdal 1.1.8 is too old.  1.2.5 works.
+
+2005-07-05  Bernhard Herzog  <bh at intevation.de>
+
+	* Resources/XML/thuban-1.1.dtd (rasterlayer): Add the opacity and
+	masktype attributes.
+
+2005-07-05  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.__mangle_bounding_box)
+	(Layer.ClipBoundingBox): Rename ClipBoundingBox to
+	__mangle_bounding_box.  See the comments in the code and RT #2845
+
+	* test/test_layer.py (TestLayer.test_arc_layer_with_projection):
+	Remove the explicit test of ClipBoundingBox.  The method isn't
+	public anymore and the direct call in the test wasn't necessary in
+	the first place.  If ClipBoundingBox (now __mangle_bounding_box)
+	isn't called, the return value of ShapesInRegion will be
+	different.
+
+2005-07-05  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/viewport.py (ViewPort.set_view_transform): Handle
+	ZeroDivisionError exceptions.  I don't know when they happen
+	exactly.  It probably happens when the projections aren't set
+	properly.
+
+2005-07-01  Bernhard Herzog  <bh at intevation.de>
+
+	First step towards unicode.  With this roughly we're at step 1
+	string_representation.txt
+
+	* Doc/technotes/string_representation.txt: New.  Document how
+	strings are represented in Thuban and how to get to a Unicode
+	Thuban.
+
+	* Thuban/__init__.py (set_internal_encoding)
+	(unicode_from_internal, internal_from_unicode): New. The first few
+	functions for the internal string representation
+
+	* Thuban/UI/about.py (unicodeToLocale): Removed.  Use
+	internal_from_unicode instead.
+
+	* Thuban/UI/__init__.py (install_wx_translation): Determine the
+	encoding to use for the internal string representation.  Also,
+	change the translation function to return strings in internal
+	representation even on unicode builds of wxPython
+
+	* Thuban/Model/load.py (SessionLoader.check_attrs): Decode
+	filenames too.
+	(SessionLoader.start_clrange): Use check_attrs to decode and check
+	the attributes.
+
+	* Thuban/Model/xmlreader.py (XMLReader.encode): Use
+	internal_from_unicode to convert unicode strings.
+
+	* Thuban/Model/xmlwriter.py (XMLWriter.encode): Use
+	unicode_from_internal when applicable
+
+	* test/runtests.py (main): New command line option:
+	internal-encoding to specify the internal string encoding to use
+	in the tests.
+
+	* test/support.py (initthuban): Set the internal encoding to
+	latin-1
+
+	* test/test_load.py (TestSingleLayer.test, TestClassification.test)
+	(TestLabelLayer.test): Use the internal string representation when
+	dealing with non-ascii characters
+
+	* test/test_load_1_0.py (TestSingleLayer.test)
+	(TestClassification.test, TestLabelLayer.test): Use the internal
+	string representation when dealing with non-ascii characters
+
+	* test/test_load_0_9.py (TestSingleLayer.test)
+	(TestClassification.test): Use the internal string representation
+	when dealing with non-ascii characters
+
+	* test/test_load_0_8.py (TestUnicodeStrings.test): Use the
+	internal string representation when dealing with non-ascii
+	characters
+
+	* test/test_save.py (XMLWriterTest.testEncode)
+	(SaveSessionTest.testClassifiedLayer): Use the internal string
+	representation when dealing with non-ascii characters where
+	applicable
+
+2005-06-30  Bernhard Herzog  <bh at intevation.de>
+
+	* test/runtests.py: Untabify.
+
+2005-06-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/renderer.py (ScreenRenderer.draw_selection_incrementally): 
+	untabify.
+
+2005-06-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Extensions/ogr/test/__init__.py: Add missing coding directive
+
+2005-06-28  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/renderer.py (ScreenRenderer.draw_selection_incrementally):
+	Use the default size for rendering selected items of default type.
+	Fixes part 2 of https://intevation.de/rt/webrt?serial_num=3149
+
+2005-06-28  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Extensions/importAPR/apr.py (APR_BShSym): Extend by 'Stripple'.
+	(APR_TClr.GetThubanColor): Fix bug in color interpretation.
+	Thanks to Frank Koormann who identified this problem.
+
+	* Extensions/importAPR/importAPR.py (APR_VShSym): New. Just
+	another symbol identified.
+
+2005-06-27  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual-de.xml: More translations.
+
+2005-05-12  Jonathan Coles <jonathan at intevation.de>
+	
+	* Thuban/UI/projdialog.py: Add missing import, which led to an
+	exception when opening a layer's projection.
+
+2005-05-09  Bernhard Herzog  <bh at intevation.de>
+
+	* test/support.py (FileLoadTestCase.filename): Fix doc-string.
+
+2005-05-09  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/postgisdb.py (PostGISConnection.connect): Set the
+	connection to autoconnect.  Fixes RT#3148.
+
+	* test/test_postgis_db.py
+	(TestPostGISSpecialCases.test_simple_error_handling): New test
+	that attempts to reproduce RT#3148.
+
+2005-05-06  Jonathan Coles <jonathan at intevation.de>
+
+	Add support for saving and loading the opacity and mask type
+	properties of RasterLayers. Also add support for proper use
+	of alpha information while drawing images not in 'RAW' format.
+	If transparency in an image format (e.g, PNG) is supported by
+	wxWidgets then the image would previously have been draw with 
+	transparent regions, but the opaque regions would have been 
+	unaffected by a change in the layer's opacity. This patch
+	corrects the problem.
+
+	* Thuban/Model/layer.py (RasterLayer): Added opacity and
+	masktype parameters to the constructor, and set the
+	appropriate variables to those values.
+
+	* Thuban/Model/load.py (SessionLoader.start_rasterlayer): Added
+	code to read the opacity and mask type of the layer and construct
+	a new layer with the additional parameters.
+
+	* Thuban/Model/save.py (SessionSaver.write_layer): Added code
+	to save the opacity and mask type of a layer.
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.draw_raster_layer): Pass
+	the opacity of the layer to draw_raster_data rather than the layer.
+	(BaseRenderer.draw_raster_data): Remove the layer parameter because
+	the function doesn't need to know about the layer. Add the optional 
+	opacity parameter whose default is 1.0. Add 'PNG' as a supported
+	graphics format.
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_raster_data): Fixed
+	signature to match that in BaseRenderer. Use the new opacity argument
+	in place of calling layer.Opacity(). In the case where the
+	format is not 'RAW', alpha_data is None and the loaded image has
+	alpha information, use the file's alpha information. This is
+	still subject to the layer's opacity setting.
+
+	* test/test_baserenderer.py (SimpleRenderer.draw_raster_data): 
+	Fixed signature to match that in BaseRenderer.
+
+	* test/test_load.py (TestRasterLayer): Change file_contents to
+	include opacity and masktype variables.
+	(TestRasterLayer.test): Include tests for opacity and masktype
+	changes.
+
+	* test/test_save.py (SaveSessionTest.testRasterLayer): Restructure
+	test to cover a variety of combinations of masktype and opacity
+	settings.
+
+2005-05-02  Jan-Oliver Wagner <jan at intevation.de>
+
+	* debian/rules: add --use-wx-python-swig-hack
+	to the build command.
+	Thanks to Moritz Lennert for pointing this out.
+
+2005-04-28  Jan-Oliver Wagner <jan at intevation.de>
+
+	Introduce OGRFileShapeStore in ogr extension.
+	This allows at least that loaded shapefile shape stores
+	can be saved correctly in the thuban session file
+	and reloaded again (reload is via core shapefile
+	routine, not OGR). For other types, .thuban files
+	can not be reloaded for the time being.
+
+	* Extensions/ogr/ogrshapes.py (OGRFileShapeStore): New. This
+	class ist to be used for any file-based shape stores
+	accessed through OGR.
+
+	* Extensions/ogr/ogrstart.py (open_with_ogr): Added
+	forgotten _ for i18n. Adapted call OpenFileShapestore
+	regarding new parameter.
+	(OpenFileShapestore): Use OGRFileShapeStore instead of
+	OGRShapeStore. Fix return value (None instead of null).
+	Add new parameter "mainwindow" to avoid accessing global
+	context.
+
+2005-04-27  Jan-Oliver Wagner <jan at intevation.de>
+
+	Introduce FileShapeStore as generalization for
+	file-based shape stores. In a first instance
+	this allows additional modules to handle shapefile
+	format as well, namely the OGR extension.
+
+	* Thuban/Model/data.py: Various small fixes in doc-strings.
+	(FileShapeStore): New class.
+	(ShapefileStore): Derive from FileShapeStore.
+	(ShapefileStore.__init__): Call __init__ of FileShapeStore,
+	rename self.table to self._table, initialize self._bbox
+	(ShapefileStore._open_shapefile): Use self._bbox instead of self.bbox
+	and self.FileName() instead of self.filename.
+	(ShapefileStore.Table): Use self._table instead of self.table.
+	(ShapefileStore.FileName): Removed (moved to FileShapeStore).
+	(ShapefileStore.BoundingBox):  Use self._bbox instead of self.bbox.
+
+	* Thuban/Model/save.py: Replace ShapefileStore by FileShapeStore.
+	(SessionSaver.write_data_containers): Only use methods of the
+	base class FileShapeStore.
+
+2005-04-26  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/wms.py (render_wms_layer): Adjusted the render
+	function to the modified render engine
+
+2005-04-25  Martin Schulze  <joey at infodrom.org>
+
+	* Thuban/UI/renderer.py (MapRenderer.projected_raster_layer):
+	Added a description according to the CVS log message
+
+2005-04-23  Martin Schulze  <joey at infodrom.org>
+
+	* Thuban/UI/renderer.py: Added a missing import
+
+2005-04-23  Russell Nelson  <nelson at crynwr.com>
+
+	* Thuban/UI/view.py (MapCanvas.OnMiddle{Up,Down}): Changed the
+	way the previous tool is remembered, so that middle-button
+	panning works even if you haven't selected a tool.
+
+2005-04-11  Bernhard Herzog  <bh at intevation.de>
+
+	* libraries/thuban/wxproj.cpp: Move the compatibility code that
+	deals with the wxPython 2.4 version of wxPython.h into the #ifdef
+	branch that includes wxPython.h because it's only needed when
+	wxPython.h is used.  Also, it won't compile when
+	USE_WX_PYTHON_SWIG_HACK is set otherwise.
+
+2005-04-07  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/classifier.py (ClassGrid.__init__): Use -1 as the ID.
+	(ID_CLASS_TABLE): Removed. It wasn't used anywhere except in
+	ClassGrid.__init__ and it's value is outside of the valid
+	range (must be < 32768).  wxPython 2.5 complains about it with an
+	exception.
+
+2005-04-05  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual-de.xml: More translations.
+
+2005-04-05  Bernhard Herzog  <bh at intevation.de>
+
+	* libraries/thuban/wxproj.cpp: Make it work with a wxPython.h from
+	wxPython 2.4 as well.  Also, remove a now obsolete comment.
+
+2005-04-05  Bernhard Herzog  <bh at intevation.de>
+
+	Use wxPython.h by default but provide a workaround when it isn't
+	available.
+
+	* setup.py (wxproj_extension): New variable.  Assign the Extension
+	instance for Lib.wxproj to this variable instead of putting it
+	directly into the listso that it can be accessed by other code
+	later.
+	(thuban_build_ext.user_options): Added boolean option
+	--use-wx-python-swig-hack.
+	(thuban_build_ext.initialize_options): Initialize the new option
+	to False.
+	(thuban_build_ext.finalize_options): If the new option was given,
+	define the preprocesser macro USE_WX_PYTHON_SWIG_HACK.
+	(thuban_build_ext): Update the doc-string
+
+	* libraries/thuban/wxproj.cpp: Normally we use
+	wx/wxPython/wxPython.h now.  Only if USE_WX_PYTHON_SWIG_HACK is
+	defined, use swigPtrConvertHack.h instead.
+
+	* libraries/thuban/swigPtrConvertHack.h: Remove the code that was
+	copied over from wxPython.h.
+	(decode_pointer_new): New.  Equivalent of decode_pointer for
+	wxPython 2.5.
+	(wxPyConvertSwigPtr): Modified to cope with wxPython 2.5 as well.
+
+	* README: Add section on potential build problems which explains
+	how the work-around for a missing wxPython.h is activated.
+
+2005-03-29  Bernhard Herzog  <bh at intevation.de>
+
+	* test/postgissupport.py (find_postgis_sql): Added yet another
+	potential location for (lw)postgis.sql because the file has moved
+	again in postgis 1.0.0 rc4.
+
+2005-03-29  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/legend.py (BMP_SIZE_W, BMP_SIZE_H): Set both to 16 to
+	match the site of the legend_icon_layer icon.  Otherwise wxpython
+	2.5 complains when the legend is created with the error:
+
+	PyAssertionError: C++ assertion "(bitmap.GetWidth() == m_width &&
+	bitmap.GetHeight() == m_height) || (m_width == 0 && m_height ==
+	0)" failed in ./src/generic/imaglist.cpp(81): invalid bitmap size
+	in wxImageList: this might work on this platform but definitely
+	won't under Windows.
+
+2005-03-23  Jonathan Coles <jonathan at intevation.de>
+
+	These changes add support for adjusting the opacity of a raster layer.
+
+	* Thuban/Model/layer.py (RasterLayer.Opacity): Replaces AlphaOpacity.
+	(RasterLayer.SetOpacity): Replaces SetAlphaOpacity. Also triggers
+	a LAYER_CHANGED event if the opacity actually changes.
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.draw_raster_data): Added
+	layer parameter needed in the implementation of this method in
+	renderer.py.
+
+	* Thuban/UI/layerproperties.py (LayerProperties.dialog_layout): Fixed
+	typo 00 -> 0.
+
+	* Thuban/UI/rasterlayerproperties.py (RasterLayerProperties): Added
+	control to adjust opacity.
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_raster_data): Scale the 
+	alpha data based on the opacity level of the layer. 
+
+	* test/test_baserenderer.py (SimpleRenderer.draw_raster_data): Now
+	accepts a layer parameter.
+
+	* test/test_layer.py (TestLayerModification.test_raster_layer): 
+	Rename opacity method calls and add test for LAYER_CHANGED.
+
+2005-03-16  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_connector.py (DeletionTestMixin.check_deletions)
+	(DeletionTestMixin.check_deletetions): renamed to check_deletions.
+	update the callers.
+
+2005-03-14  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual-de.xml: More translations.
+
+2005-03-10  Jan-Oliver Wagner <jan at intevation.de>
+
+	Introducing initialization callbacks for extensions.
+
+	* Thuban/UI/extensionregistry.py (ExtensionDesc.__init__): Added
+	optional parameter init_callback.
+	(ExtensionDesc.init_ext): New. Executes the callback and sets
+	a status.
+
+	* Thuban/UI/application.py (ThubanApplication.OnInit): Add the
+	initialization of the extensions.
+	(ThubanApplication.init_extensions): Init all extensions.
+
+	* Thuban/UI/about.py (About.__init__): Added status of the extensions
+	to the about text.
+
+	* Extensions/gns2shp/__init__.py: Added init method for Extension
+	description.
+	(init): New. Contains the initialization of the module.
+
+2005-03-04  Nina Hüffmeyer <nhueffme at intevation.de>
+
+	* Extensions/ogr/ogrdialog.py: Added a dialog, which asks for
+	OGRConnection to open a datasource. Removed dialog to display all
+	available drivers. Added some doc strings.
+
+	* Extensions/ogr/ogrstart.py: Added menu entry for opening an
+	OGRDatasource with a string. Added two opening methods which return an
+	OGRDatasource (either data from file or from DB).
+
+	* Extensions/ogr/ogrshapes.py: Added class OGRGeometry, which
+	represents a geometry reference of an OGRFeature. OGRShape now has a
+	list of referenced geometry objects (important for geometry
+	collections).
+	For OGRShapeStores loaded from a DB an ID column can be specified now.
+
+2005-02-22  Jan-Oliver Wagner <jan at intevation.de>
+
+	* test/test_map.py (TestMapWithContents.test_tree_info):
+	Added label layer for comparison.
+
+2005-02-18  Jonathan Coles <jonathan at intevation.de>
+
+	* libraries/thuban/gdalwarp.cpp (GetImageData): Optimize the loop
+	which builds a mask. Handle the majority of an image in a loop,
+	creating 8 bits at a time. Later, handle the edge case where less
+	than 8 bits are packed. 
+
+2005-02-18  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_baserenderer.py (TestBaseRenderer.setUp): Fix
+	doc-string
+
+2005-02-18  Jonathan Coles <jonathan at intevation.de>
+
+	* setup.py: Remove wx_cs_params from gdal compile options.
+
+2005-02-18  Jonathan Coles <jonathan at intevation.de>
+
+	Refactored baserenderer.py and renderer.py to remove baserenderer.py's
+	dependencies on wxPython. Added a new method projected_raster_layer()
+	that returns a raster layer image in projected space. This must be
+	implemented in classes derived from BaseRenderer. This also eliminates
+	the dependency on gdal in baserenderer.py.
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.draw_raster_layer): Call
+	new projected_raster_layer() to get projected raster image instead
+	of directly calling ProjectRasterFile().
+	(BaseRenderer.projected_raster_layer): New. This must be implemented
+	by derived classes. It takes almost the same arguments as ProjectRasterFile
+	did and returns a projected image with mask and alpha data (if requested).
+	(BaseRenderer.render_map_incrementally): Remove the check for gdal since
+	that check will be done in MapRenderer.projected_raster_layer(). This
+	also allows other implementations to use different projection code.
+
+	* Thuban/UI/renderer.py (MapRenderer.projected_raster_layer):
+	Implementation of BaseRenderer.projected_raster_layer. Checks for 
+	gdal support and wxPython version. Also handles exceptions from
+	ProjectRasterFile.
+
+	* libraries/thuban/gdalwarp.cpp: Removed checks for wxPython versions
+	and added a variable which can be set through the options argument
+	of ProjectRasterFile.
+
+	* test/test_baserenderer.py (SimpleRenderer.projected_raster_layer): New.
+	Calls ProjectRasterFile and returns the result.
+	(TestBaseRenderer.test_projected_raster_layer): New. Tests the results
+	of calling projected_raster_layer() with different options.
+	(TestBaseRenderer.test_raster_no_projection): Removed tests based on
+	wxPython version and all tests of masks and alpha channels. These are
+	now in test_projected_raster_layer().
+
+2005-02-17  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/Model/map.py, Thuban/Model/label.py: Fixed
+	doc-strings to comply with coding_guidelines.
+
+2005-02-17  Jan-Oliver Wagner <jan at intevation.de>
+
+	Docstring improvements and minor fixes for labellayer.
+
+	* Thuban/Model/map.py:
+	(Map, Map.Destroy, Map.RemoveLayer, Map.ClearLayers,
+	Map.Layers, Map.HasLayers, Map.MoveLayerToTop,
+	Map.RaiseLayer, Map.LowerLayer, Map.MoveLayerToBottom,
+	Map.ProjectedBoundingBox, Map.GetProjection): Improved/added
+	doc string.
+	(Map.BoundingBox): Removed superfluous test for label_layer
+	and improved doc string.
+	(Map.TreeInfo): Added label_layer and improved sdo string.
+
+	* Thuban/Model/label.py: Added import of _.
+	(Label, Label.__init__): Improved/added doc string.
+	(LabelLayer, LabelLayer.__init__, LabelLayer.Labels,
+	LabelLayer.RemoveLabel, LabelLayer.ClearLabels):
+	Improved/added doc string.
+	(LabelLayer.AddLabel): Use already defined names for
+	align strings and improved doc string.
+	(LabelLayer.TreeInfo): New. Return the object data for
+	the tree view.
+
+2005-02-16  Jonathan Coles <jonathan at intevation.de>
+
+	Further wxPython 2.5 changes using patches from Daniel Calvelo Aros 
+	so that that wxproj doesn't crash. Added GUI support for selecting
+	alpha channel (opacity can't be selected yet).
+
+	NOTE: If wxPython.h is including in future distribution packages
+	then it will not be necessary to have the files swigPtrConvertHack.h
+	and wxPython_int.h included with Thuban. This is hopefully
+	a temporary workaround.
+
+	* setup.py (thuban_build_ext.finalize_options): gdalwarp needs
+	access to the macro wxCHECK_VERSION so that it will properly 
+	generate a bit mask. There was a problem between wx2.4 and wx2.5
+	that this works around.
+
+	* Thuban/Model/layer.py (RasterLayer.UseMask): Removed in favor
+	of RasterLayer.MaskType.
+	(RasterLayer.SetUseMask): Removed in favor of RasterLayer.SetMaskType
+	(RasterLayer.MaskType): New. Returns the type of mask to use. Can
+	specify none, a bitmap, or an alpha channel.
+	(RasterLayer.SetMaskType): New. Set what kind of mask to use.
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.draw_raster_layer):
+	Set the raster warping options for the mask based on the value
+	of RasterLayer.MaskType.
+
+	* Thuban/UI/legend.py (LegendTree.__FillTreeLayer): Remove 
+	deprecated calls to SetItemSelectedImage in favor of SetItemImage
+	with wxTreeItemIcon_Selected.
+
+	* Thuban/UI/rasterlayerproperties.py: Support selecting to use
+	an alpha channel for the mask.
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_raster_data): Use alpha
+	data if it is available and an alpha channel is supported under
+	the current version of wxPython.
+
+	* libraries/thuban/gdalwarp.cpp (GetImageData): Added compiler define
+	to select whether 1's or 0's select the desired portion of an image
+	in the bit mask. wx2.4 has a bug where the documentation is the opposite
+	from behavior.
+	(ProjectRasterFile): Only generate an alpha channel if the version
+	of wxPython is >= 2.5.3.
+
+	* libraries/thuban/wxproj.cpp: Applied patches from Daniel Calvelo Aros.
+	When wxPython >= 2.5.3 use the special swig functions to decode an
+	object's address.
+
+	* libraries/thuban/swigPtrConvertHack.h: Includes conditional code
+	based on the version of wxPython. If >= 2.5.3 use the special swig
+	functions from wxPython to decode wxPython objects, otherwise use
+	the old method of retrieving the address from the object __repr__ string.
+
+	* libraries/thuban/wxPython_int.h: Copied from wxPython source. 
+	Unnecessary code was removed to make it smaller. 
+
+	* test/test_baserenderer.py (TestBaseRenderer.test_raster_no_projection):
+	Add tests for returning an alpha channel.
+
+	* test/test_layer.py (TestLayerModification.test_raster_layer): Fix
+	tests that used removed functions UseMask and SetUseMask
+
+
+2005-02-08  Bernhard Herzog  <bh at intevation.de>
+
+	More wxPython 2.5 changes.  This time taken from a patch from
+	Daniel Calvelo Aros.
+
+	* Thuban/UI/tableview.py (QueryTableFrame.__init__)
+	(QueryTableFrame.__init__): Pass the size of a spacer as a single
+	item.
+
+	* Thuban/UI/projdialog.py (ProjFrame.build_dialog)
+	(ProjFrame.build_dialog): Pass the size of a spacer as a single
+	item.
+
+	* Thuban/UI/dbdialog.py (ChooseDBTableDialog.__init__): Pass the
+	size of a spacer as a single item.
+
+	* Thuban/UI/classifier.py (Classifier.dialog_layout): Pass the
+	size of a spacer as a single item.
+
+2005-02-08  Bernhard Herzog  <bh at intevation.de>
+
+	Compatibility with wxPython 2.5.  The changes should make it work
+	better with 2.5 while still keeping compatibility with 2.4.  There
+	are still problems with 2.5, though.
+
+	* Thuban/UI/dock.py (DockableWindow.__CreateBorder): Pass the size
+	of a spacer as a single item.
+
+	* Thuban/UI/classifier.py (ClassGroupPropertiesCtrl): Derive only
+	from wxControl
+
+	* Thuban/UI/legend.py (LegendTree): When running with wxPython <
+	2.5, add an implementation of the GetFirstChild method that does
+	not require the second parameter.
+	(LegendTree.find_layer, LegendTree._OnMsgMapLayersAdded)
+	(LegendTree._OnMsgMapLayersRemoved, LegendTree.DeleteAllItems)
+	(LegendTree.DeleteChildren, LegendTree.__ShowHideLayer): Do not
+	pass the second parameter to GetFirstChild
+
+2005-02-08  Nina Hüffmeyer <nhueffme at intevation.de>
+
+	* Extensions/ogr/ogrshapes.py: Removed some print commands.
+
+	* Extensions/ogr/ogrstart.py: Changed the GUI. OGR is no longer an
+	additional menu but appears as a possibility in the menu Map.
+
+2005-02-07  Jonathan Coles <jonathan at intevation.de>
+	* libraries/thuban/gdalwarp.cpp: Removed the macros PYTHON_ERR
+	and PYTHON_ERRF since they were no longer necessary.
+
+2005-02-07  Bernhard Reiter <bernhard at intevation.de>
+	* Thuban/UI/classifier.py (ClassGrid.DeleteSelectedRows):
+	Enable translation for message string.
+
+2005-02-06  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/infodialog.py (wmsInfoDialog.__init__): Adjusted
+	the arguments of the contstructor to fit the global scheme
+
+2005-01-31  Nina Hüffmeyer <nhueffme at intevation.de>
+
+	* Extensions/ogr/ogrdialog.py: Added class ogrdialog.py, which provides
+	some dialogs needed to start ogr.
+	
+	* Extensions/ogr/__init__.py: Changed comments to avoid encoding
+	warnings.
+
+	* Extensions/ogr/test/test_OGRShapestore.py: Changed comments to avoid
+	encoding warnings.
+
+2005-01-28  Jonathan Coles <jonathan at intevation.de>
+
+	* libraries/thuban/gdalwarp.cpp (GetImageData): Recode how the
+	mask is packed into a bit array. It's now slightly faster.
+
+2005-01-28  Jonathan Coles <jonathan at intevation.de>
+
+	* Thuban/Model/layer.py (RasterLayer.__init__): Make use_mask
+	default to true.
+
+	* Thuban/Model/load.py (SessionLoader.start_rasterlayer): Remove 
+	code that loads the state of the layer's use_mask flag. Its 
+	usefulness is still being debated.
+
+	* Thuban/Model/save.py (SessionSaver.write_layer): Remove
+	code that saves the state of the layer's use_mask flag. Its 
+	usefulness is still being debated.
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.draw_raster_layer): Pass
+	options to ProjectRasterFile based on the state of layer.UseMask().
+	Catch more exceptions from ProjectRasterFile so that Thuban doesn't
+	quit is there is a problem projecting.
+	(BaseRenderer.draw_raster_data): Change the documentation to 
+	describe the new format (XBM) that the mask data will be in.
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_raster_data): The mask
+	data is in XBM format when format='RAW' which means it doesn't 
+	need to be converted to a wxImage before being used as a mask
+	for a wxBitmap. Assume that if format != 'RAW' that the image
+	data and mask data are in the same format.
+
+	* libraries/thuban/gdalwarp.cpp (GetImageData): If alpha is enabled
+	and a mask is requested, convert the alpha band to a bit array in 
+	XBM format. if an alpha channel is requested, simply return the 
+	data in the alpha band. Provide better error handling by returning
+	python error messages (also fixes RT #2947).
+	(ProjectRasterFile): Support multiple mask options, rather than simply
+	a flag indicating that a mask should or should not be used. Provide 
+	better error handling by returning python error messages.
+
+	* test/test_baserenderer.py (TestBaseRenderer.test_raster_no_projection):
+	Add mask data to test.
+
+	* test/test_layer.py (TestLayer.test_raster_layer): Test that a layer
+	should use the mask by default.
+	(TestLayerModificaton.test_raster_layer): Test that a layer should use 
+	the mask by default.
+
+	* test/test_load.py (TestRasterLayer.test): Remove testing for
+	use_mask flag in file.
+
+	* test/test_save.py (SaveSessionTest.testRasterLayer): Remove testing
+	for use_mask in file.
+
+	* test/test_load_1_0_1.py: Removed. Shouldn't have been checked in.
+	
+2005-01-26  Jonathan Coles <jonathan at intevation.de>
+
+	Add a new dialog box for raster layers. The dialog box allows
+	the user to toggle a mask that is generated by ProjectRasterFile
+	and is used to only draw the real parts of the projected image.
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.draw_raster_layer):
+	Instruct the warping code to generate a mask if the raster layer 
+	requests one. 
+	(BaseRenderer.draw_raster_data): Removed obsolete optional mask argument.
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_raster_data): Removed
+	obsolete optional mask argument.
+
+	* Thuban/UI/classifier.py (Classifier): Change the parent class
+	to LayerProperties and rework the code to support layout calls
+	from the parent.
+	(Classifier.dialog_layout): New. Layout the dialog box.
+	(Classifier.map_layers_removed): Removed. Moved to parent class.
+	(Classifier.map_replaced): Removed. Moved to parent class.
+	(Classifier._OnTry): Renamed to OnTry to support parent class.
+	(Classifier.OnClose): Removed. Supplied in parent class.
+	(Classifier._OnCloseBtn): Removed. Supplied in parent class as OnCloseBtn.
+	(Classifier._OnOK): Renamed to OnOK to support parent class.
+	(Classifier._OnRevert): Renamed to OnRevert to support parent class.
+
+	* Thuban/UI/layerproperties.py: New. Base class for layer properties
+	dialog boxes.
+
+	* Thuban/UI/rasterlayerproperties.py: New. Class for displaying
+	raster layer properties.
+
+	* libraries/thuban/gdalwarp.cpp: Replace the old gdalwarp.cpp code
+	with the non-simple version supplied with gdal. This allows added
+	features such as creating an alpha band.
+	(GetImageData): Generate a mask array from the alpha band that is 
+	generated by gdal if the user has selected it. Try to support images 
+	that have more than three bands, such as images with RGB plus an 
+	alpha band.
+	(ProjectRasterFile): Convert python argument for mask and tell
+	gdal to enable or disable an alpha band.
+
+	* Thuban/Model/layer.py (BaseLayer.Type): New. Returns a string
+	describing what kind of layer the class is. Defaults to "Unknown",
+	but should be overridden by subclasses.
+	(Layer.Type): New. Override base class method.
+	(RasterLayer.__init__): Create a flag for using a mask. Record extra 
+	data from gdal for display in the properties dialog.
+	(RasterLayer.Type): New. Override base class method.
+	(RasterLayer.UseMask): New. Returns True if the mask should be used.
+	(RasterLayer.SetUseMask): New. Set if the mask should be used.
+	(RasterLayer.ImageInfo): New. Return extra information about the image.
+
+	* Thuban/Model/load.py (SessionLoader.start_rasterlayer): Load
+	the mask information.
+
+	* Thuban/Model/save.py (SessionSaver.write_layer): Save mask information.
+
+	* Thuban/UI/mainwindow.py: Register the RasterLayerProperties and
+	Classifier classes as dialogs to use with the proper layer types.
+
+	* test/test_baserenderer.py (TestBaseRenderer.test_raster_no_projection):
+	Fix test.
+
+	* test/test_layer.py (TestLayer.test_raster_layer): Test new methods.
+	(TestLayerModification.build_path): New. Support function.
+	(TestLayerModification.test_raster_layer): New. Test new methods.
+
+	* test/test_save.py (SaveSessionTest.testRasterLayer): Add tests for mask.
+
+	* test/test_load.py (TestRasterLayer): Add tests for mask.
+
+	* test/test_load_1_0_1.py: New. Copied from test_load.py.
+
+	* test/test_baserenderer.py (SimpleRenderer.draw_raster_data): Removed
+	obsolete optional mask argument.
+
+2005-01-26  Nina Hüffmeyer <nhueffme at intevation.de>
+
+	* Extensions/ogr/ogrshapes.py: Added two dictionaries to ShapeStore 
+	which maps the ids and the ordinals. Fixed RowIdToOrdinal(),
+	RowOrdinalToId() and ReadRowAsDict().
+
+	* Extensions/ogr/ogrstart.py: Added menu item which opens database
+	layers for existing database connections.
+
+	* Extensions/ogr/test/test_OGRShapestore.py: Fixed a message string.
+
+
+2005-01-26  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual-de.xml: More translations.
+
+2005-01-24  Bernhard Herzog  <bh at intevation.de>
+
+	Rework the status bar updates a bit to make sure the message about
+	the projections is produced at the right times.
+
+	* Thuban/UI/mainwindow.py (MainWindow.update_status_bar_messages):
+	New class variable with messages that may require a status bar
+	update.
+	(MainWindow.view_position_changed)
+	(MainWindow.update_status_bar): Rename from view_position_changed
+	to update_status_bar.  It's meaning has changed now that it may
+	also generate messages about problems with projection settings.
+	(MainWindow.__init__): Use the new update_status_bar_messages
+	class variable to subscribe update_status_bar
+	(MainWindow.set_position_text): Update doc-string.  This method
+	has to be renamed at some point.  See doc-string and comments.
+	(MainWindow.OnClose): Unsubscribe update_status_bar from all
+	messages in update_status_bar_messages
+
+	* Thuban/UI/viewport.py (ViewPort.forwarded_map_messages): New
+	class attribute.  map messages to be forwarded by the viewport.
+	(ViewPort._subscribe_map, ViewPort._unsubscribe_map): (un)subscribe
+	the messages in forwarded_map_messages
+
+2005-01-21  Bernhard Herzog  <bh at intevation.de>
+
+	* test/postgissupport.py (PostGISDatabase.__init__): Tweak
+	doc-string
+	(find_postgis_sql): Update for postgis-1.0.0-rc1, which uses a
+	different name for the initialization SQL file.
+
+2005-01-21  Jonathan Coles <jonathan at intevation.de>
+
+	* Thuban/UI/baserenderer.py (proj_params_to_str): New. Takes
+	a projection and returns a formatted string representing the 
+	parameters to feed to gdalwarp. This function eliminates
+	redundancy in draw_raster_layer().
+	(BaseRenderer.render_map_incrementally): Removed the optimization which
+	drew the top most raster layer first and then only those vector-
+	based layers that are above it. With the support for transparency
+	this optimization breaks correct behaviour.
+	(BaseRenderer.draw_raster_layer): Reorganize code to support possible
+	future enhancements to raster layer bounding box. The old behaviour has
+	not changed. Also, change calling parameters to draw_raster_data()
+	to specify new RAW data format and mask.
+	(BaseRenderer.draw_raster_data): Change signature to include an optional
+	parameter for mask information. Change documentation to mention
+	support for new parameter and added option for RAW data format.
+	The data argument is now a list of [width, height, data].
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_raster_data): Add new optional
+	mask parameter. Add new condition for RAW format, which 
+	significantly reduces rendering time. Add condition for 
+	mask parameter.
+
+	* libraries/thuban/gdalwarp.cpp (GetImageData): New. Creates a 
+	data array of RGB values from the projected image returned from 
+	the gdal warping functions. In the case of palette based images, it
+	converts the NO_DATA index to the mask color.
+	(ProjectRasterFile): Removed all custom memory driver references
+	and replaced it with the standard in-memory dataset provided
+	by gdal. The return data is no longer a BMP file, but an array
+	of RGB values, one set triple per pixel.
+
+	* libraries/thuban/bmpdataset.cpp: Removed. Unnecessary.
+	* libraries/thuban/cpl_mfile.h: Removed. Unnecessary.
+	* libraries/thuban/cpl_mfile.cpp: Removed. Unnecessary.
+
+	* setup.py (thuban_build_ext.finalize_options): Removed mention
+	of cpl_mfile.cpp and bmpdataset.cpp files in the list of source
+	files. These are obsolete with the new version of gdalwarp.cpp
+
+	* test/test_baserenderer.py (SimpleRenderer.draw_raster_data):
+	Updated signature.
+	(TestBaseRenderer.test_raster_no_projection): Changed the test
+	data to be data in the uncompressed RAW format returned from
+	ProjectRasterFile.
+
+2005-01-21  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.view_position_changed): Made
+	string available for i18n.
+
+2005-01-20  Russell Nelson  <nelson at crynwr.com>
+
+	* Resources/Projections/defaults.proj: Ruin the speling of the
+	Lambert-93 projection so it doesn't run into the wx UTF-8 bug.
+	It's the wrong thing to do in the long run, but it's necessary for
+	those users until that bug is fixed.  Otherwise the projection
+	dialog segfaults.  Better to annoy some Lambert-93 users with a
+	spelling mistake than every Fedora Core 3 user of Thuban-CVS.
+
+2005-01-20  Bernhard Reiter <bernhard at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.view_position_changed): Added
+	docstring and comment that the warning code here is a hack.
+
+2005-01-20  Russell Nelson  <nelson at crynwr.com>
+
+	* Thuban/UI/mainwindow.py (MainWindow.view_position_changed): Warn
+	user about misprojected layers when their lat/lon bounding
+	box exceeds rational lat/lon values.
+
+2005-01-20  Bernhard Reiter <bernhard at intevation.de>
+
+	* Thuban/UI/about.py (unicodeToLocale): Improved:
+	Use 'ascii' and then 'replace' for other characters 
+	when getdefaultlocale returns None. Thanks to Bernhard H. .
+
+2005-01-20  Bernhard Reiter <bernhard at intevation.de>
+
+	* Thuban/UI/classgen.py (GenQuantilesPanel.OnRetrieve): Added a comment
+	that OnRangeText might be called twice and using None as argument.
+
+2005-01-20  Bernhard Reiter <bernhard at intevation.de>
+
+	* Thuban/UI/classgen.py (GenQuantilesPanel.OnRetrieve): Add a
+	OnRangeText(0) to work around a different in wx Behaviour noticed
+	on MacOSX, thanks to Lorenzo Moretti and Daniel Calvelo for the fix.
+
+2005-01-20  Bernhard Reiter <bernhard at intevation.de>
+
+	* Thuban/UI/about.py: take iso-8859-15 when getdefaultlocale returns
+	None. (Fixes rt#2910.)
+	
+2005-01-18  Frank Koormann <frank at intevation.de>
+
+	New Extension: mouseposition
+	Tool to collect mouse click positions (map coordinates) in a dialog.
+ 
+	* Extensions/mouseposition/__init__.py: New, extension registration
+
+	* Extensions/mouseposition/mouseposition.py: New, implements the 
+	dialog and adds a tool to Thuban mainwindow.
+
+	* Extensions/mouseposition/position.xpm: New, icon for tool.
+
+2005-01-14  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual-de.xml: More translations.
+
+2005-01-11  Frank Koormann <frank at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.DuplicateLayer):
+	Fix indention bug.
+
+2005-01-09  Frank Koormann <frank at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.DuplicateLayer):
+	BugFix 2901: Explicitly copy layers ClassificationColumn since it 
+	is not part of the layers Classification.
+
+2005-01-03  Frank Koormann <frank at intevation.de>
+
+	* Thuban/UI/renderer.py (ScreenRendererdraw_selection_incrementally):
+	BugFix 2883: Former implementation only worked on classified point 
+	layers: KeyError was raised, now use the default size if field is None. 
+
+2004-12-27  Bernhard Reiter <bernhard at intevation.de>
+
+	svgexport 1.0.0cvs: Fixed label export.
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	class TestSVGRenderer(): New class; new test test_label_font().
+
+	* Extensions/svgexport/svgmapwriter.py
+	(SVGRenderer.label_font()): initialised Font size with self.factor now, 
+	makes test_label_font happy.
+
+	* Extensions/svgexport/TODO: crossed out fixed label export item.
+	Added item for options.
+
+	* Extensions/svgexport/__init__.py: Bumped version to 1.0.0cvs.
+
+2004-12-27  Russell Nelson  <nelson at crynwr.com>
+
+	Middle mouse button pans.
+
+	* Thuban/UI/view.py (MapCanvas.__init__): Subscribe also
+	OnMiddleDown and OnMiddleUp events.
+	(MapCanvas.OnMiddleDown): New. Activate the pan tool and remember the
+	previously used tool.
+	(MapCanvas.OnMiddleUp): New. Reactivate the remebered tool used before
+	pressing the middle mouse button.
+
+2004-12-27  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual-de.xml: More translations.
+
+2004-12-23  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/projdialog.py (ProjFrame.load_user_proj): Added a
+	\n to stderr after the warnings. Thanks to Russell Nelson.
+
+2004-12-20  Nina Hueffmeyer <nhueffme at intevation.de>
+
+	* Extensions/ogr/ogrshapes.py: Fixed some issues from 
+	Bernhard (coding guidelines etc.). Additionally it is now possible to 
+	display shapefiles containing feature collections (e.g.polygons 
+	with holes). Works with gdal 1.2.1 now.
+
+	* Extensions/ogr/test/test_OGRShapestore.py: Fixed some issues
+	from Bernhard (coding guidelines etc.). If ogr can't be imported,
+	tests are skipped now.
+
+	* Extensions/ogr/ogrstart.py: Fixed some typings.
+
+2004-12-20  Bernhard Reiter <bernhard at intevation.de>
+
+	* Extensions/svgexport/TODO: updated to add support for 
+	raster layers and labels for 1.0.1.
+
+	* Extensions/svgexport/svgmapwriter.py (draw_raster_layer):
+	Issue a warning now.
+
+2004-12-19  Bernhard Reiter <bernhard at intevation.de>
+
+	* Extensions/svgexport/TODO: Added idea to support triggering
+	the application down the pipe.
+
+2004-12-19  Bernhard Reiter <bernhard at intevation.de>
+
+	svgexport: Improved code quality, mainly by better naming.
+
+	* Extensions/svgexport/svgmapwriter.py:
+	DrawPath() renamed to DrawPolygonPath(),
+	added documentation, improved comments and variable names.
+	
+	* Extensions/svgexport/svgmapwriter.py,
+	  Extensions/svgexport/test/test_svgmapwriter.py:
+	All using DrawPolygonPath() now, the default parameter closed=True
+	omitted.
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	renamed test_polygon_opened() to test_polyline()
+	renamed test_transparent_polygon() to test_transparent_polyline()
+
+2004-12-18  Jan-Oliver Wagner <jan at intevation.de>
+
+	Some fixes of gns2shp extension.
+
+	* Extensions/gns2shp/test/__init__.py: New. Make this directory a
+	package.
+
+	* Extensions/gns2shp/test/test_gns2shp.py: Add some import paths
+	dynamically.
+
+	* Extensions/gns2shp/test/README: Simplified description how to test.
+
+	* Extensions/gns2shp/gns2shp.py (gns2shp): Fixed doc-string,
+	fixed some dimensions of fields according to the GNS documentation
+	which seems to change undocumented.
+	Now killing trailing \n and/or \r from MODIFY_DATE.
+	This fixes RT#2453.
+
+2004-12-18  Bernhard Reiter <bernhard at intevation.de>
+
+	svgexport 1.0.0: Treats holes and islands nicely. Documentation added.
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	Added new tests: test_export_polygon_with_hole() 
+	and test_polygon_with_hole().
+
+	* Extensions/svgexport/svgmapwriter.py
+	(draw_polygon_shape()): Uses DrawPath correctly now.
+
+	* Doc/manual/thuban-manual.xml: Added documentation for stable
+	extention svgexport.	
+	* Doc/manual/thuban-manual-de.xml: Copied English section about
+	svexport over.
+
+	* Extensions/svgexport/__init__.py: Bumped version number to 1.0.0.
+
+	* Extensions/svgexport/svgsaver.py,maplegend.py: 
+	Moved from experimental to stable extension menu.
+
+	* Extensions/svgexport/TODO: updated.
+
+
+2004-12-18  Bernhard Reiter <bernhard at intevation.de>
+
+	Added Extensions/svgexport/TODO
+
+2004-12-18  Bernhard Reiter <bernhard at intevation.de>
+
+	Refactored in svgexport:
+	DrawPath replaces DrawPolygon; added newline in front of "M" in paths.
+
+	* Extensions/svgexport/svgmapwriter.py
+	Added verbosity level 3 to print out polygon points.
+	(class Point): added __repr__
+	(class Brush, __str__()): Added space after ,.
+	(DrawPolygon): Renamed to DrawPath()
+	(DrawPath): Takes list of polygons as input now, adds \n before "M"s.
+	(DrawLines): Using DrawPath now.
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	Replaced DrawPolygon() calls with DrawPath() and put the first argument
+	inside another list. Adapted test data with a newline before "M".
+
+2004-12-18  Bernhard Reiter <bernhard at intevation.de>
+	
+	Refactored svgexport tests: 9 double tests runs eliminated; 
+	code size reduced by 8 lines.
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	(class TestWithDC): Renamed to BaseTestWithDC, moved to top.
+	(class BaseWithDCtools): New, subclass from BaseTestWithDC.
+	(class TestDrawSplines): now subclass from BaseTestWithDCtools, 
+	this fixed the double running of the nine tests of TestVirtualDC.
+	(class TestVirtualDC): Using self.dc and self.file from setUp().
+
+2004-12-17  Bernhard Herzog  <bh at intevation.de>
+
+	Two windows specific fixes ported from thuban-1­0-branch:
+
+	* Thuban/UI/about.py (unicodeToLocale): Use getdefaultlocale
+	instead of getlocale because getlocale doesn't return a usable
+	encoding name on a german windows 2000
+
+	* setup.py: windows build: Removed the absolute path names and
+	made all prfixes relative to the directory containing setup.py.
+	Makes it a little easier to adapt to a different system.
+
+2004-12-16  Bernhard Herzog  <bh at intevation.de>
+
+	Add support for PostGIS tables with LINESTRING geometries.
+	Fixes RT#2299
+
+	* Thuban/Model/postgisdb.py (shapetype_map): Add LINESTRING
+
+	* test/postgissupport.py
+	(PostgreSQLServer.get_default_static_data_db): Rename the "roads"
+	table to "roads-multi" because it now uses MULTILINESTRING
+	geometries and introduce a new "roads" table that uses LINESTRING
+	(coords_to_multilinestring): Make the doc string more precise
+	(coords_to_linestring): New.  Create a LINESTRING WKT
+	representatin
+	(wkt_converter): Add coords_to_linestring
+	(upload_shapefile): Rephrase the doc-string a bit.
+
+	* test/test_postgis_db.py (TestPostGISShapestoreArc)
+	(LineStringTests)
+	(TestPostGISShapestoreLineString)
+	(TestPostGISShapestoreMultiLineString): Split
+	TestPostGISShapestoreArc into a base class LineStringTests and two
+	derived classes TestPostGISShapestoreLineString for LINESTRING
+	geometries and TestPostGISShapestoreMultiLineString for
+	MULTILINESTRING geometries.  Most test methods are in the base
+	class with the exception of tests that explicitly check the raw
+	format.
+
+2004-12-16  Bernhard Herzog  <bh at intevation.de>
+
+	Make the test suite work with PostGIS 0.8.2 and PostgreSQL 7.4
+
+	* test/postgissupport.py (find_postgis_sql): Different postgis
+	versions put the postgis.sql file into slightly different places
+	so we have to look in both.  The updated doc string describes this
+	is more detail.
+
+	* test/test_postgis_db.py
+	(TestPostGISSpecialCases.test_column_name_quoting): The return
+	value of UniqueValues is unsorted, so it has to be sorted for
+	comparison.
+
+2004-12-16  Bernhard Herzog  <bh at intevation.de>
+
+	Fix for RT#2237
+
+	* Thuban/UI/projdialog.py (ProjFrame._show_proj_panel): If the
+	panel to be shown is the UnknownProjPanel disable the OK and Try
+	buttons.  Otherwise enable them.
+	(ProjFrame.__GetProjection): The UnknownProjPanel returns None for
+	the parameters.  In that case __GetProjection also returns None
+	now.
+
+2004-12-15  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/classgen.py (GenQuantilesPanel.__init__): Set the
+	minimum number of classes to 2.  The calculate_quantiles needs at
+	least two and raises an exception otherwise.  
+	Fixes RT#2549
+
+2004-12-15  Bernhard Herzog  <bh at intevation.de>
+
+	* test/postgissupport.py (PostgreSQLServer.execute_sql): Extend to
+	so that it returns a result for select statements.
+	(PostgreSQLServer.server_version): New.  Return the version of the
+	server software.
+	(PostgreSQLServer.require_authentication): The format of
+	pg_hba.conf has changed between PostgrSQL 7.2 and 7.3.  Check the
+	server version and generate the file in the correct format
+
+2004-12-15  Bernhard Herzog  <bh at intevation.de>
+
+	* test/postgissupport.py (PostgreSQLServer.is_running): Fix typo
+	in the doc string and rephrase it a little.
+
+2004-12-15  Frank Koormann <frank at intevation.de>
+
+	* test/test_load.py (TestAltPath.checkSession): New, extended checks if
+	session has been loaded successfully. The check is called by the relevant
+	tests after executing load_session().
+
+2004-12-13  Bernhard Herzog  <bh at intevation.de>
+
+	Make sure the region used to determine which shapes are visible
+	actually matches the region on the printed page.  If this isn't
+	done properly some shapes might not be printed.  
+	Fixes RT #2692
+
+	* Thuban/UI/view.py (MapPrintout.draw_on_dc): The region for the
+	renderer has to be at the same position as the mapregion
+
+	* Thuban/UI/renderer.py (ExportRenderer.RenderMap): self.region
+	has to be moved by (self.shiftx, self.shifty) too.
+
+2004-12-13  Bernhard Herzog  <bh at intevation.de>
+
+	* libraries/pyprojection/Projection.i: Work around a bug in the
+	generated python code which leads to exception in the __del__
+	method when the constructor fails.  See the comments in the code
+	for more details.
+
+	* libraries/pyprojection/Projection.py: Updated from Projection.i
+	with SWIG.
+
+2004-12-13  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_load.py (TestAltPath.test_01_single_path_error_fix)
+	(TestAltPath.test_02_path_error_fix_from_list)
+	(TestAltPath.test_05_path_error_fix_from_list_changed)
+	(TestAltPath.test_06_path_error_fix_from_list_fails): self.session
+	is destroyed in tearDown, so there's no need to do it in a test
+	case.
+
+	* Thuban/Model/load.py (SessionLoader.open_shapefile): Remove a
+	debug print
+
+2004-12-13  Bernhard Herzog  <bh at intevation.de>
+
+	* Extensions/svgexport/test/test_svgmapwriter.py
+	(TestDrawSplines.setUp): Do not use super with the unittest
+	classes because in Python 2.2 they're still old-style classes.
+
+2004-12-13  Frank Koormann <frank at intevation.de>
+
+    Alternative Path feature: When loading a (moved) session where 
+	shapefiles cannot be found, ask the user. Use the specified path 
+	if further shapefiles are missing. However, ask the usr for confirmation 
+	in such cases.
+
+	* test/test_load.py (TestAltPath): New, tests for alternative path feature
+	in load_session()
+	(Shapefile_CallBack): Helper, implements controllable callback.
+
+	* Thuban/UI/application.py (ThubanApplication.OnInit): 
+	Added "alt_path" to self.path
+	(ThubanApplication.OpenSession): Added shapefile_callback as second 
+	callback similar to db_connection_callback.
+	(ThubanApplication.run_alt_path_dialog): New, implementaion of
+	shapefile_callback. In addition to raising the dialog the control of
+	self.path('alt_path') is implemented here.
+
+	* Thuban/Model/load.py (SessionLoader.__init__): Added shapefile_callback.
+	(SessionLoader.open_shapefile): Open shapefile, eventually with 
+	alternative path. This wrapps the "theSession.OpenShapefile(filename)" 
+	formerly used in start_fileshapesource()/start_layer().
+	(SessionLoader.start_fileshapesource): Call open_shapefile().
+	(SessionLoader.start_layer): Call open_shapefile().
+	(load_session): Added shapefile_callback.
+
+	* Thuban/UI/altpathdialog.py: New, implements dialogs for alternative path
+	feature (search / check).
+	
+	* Doc/manual/thuban-manual.xml: Added documentation of new feature.
+
+2004-12-11  Bernhard Reiter <bernhard at intevation.de>
+
+	 svgexport 0.9.2: Point size supports for maps.
+
+	* Extensions/svgexport/svgmapwriter.py: Added import of SHAPETYPE_POINT
+	(def draw_point_shape): new parameter size defaults to 2 as before.
+	(draw_shape_layer_incrementally): Moved draw_func log line higher.
+	Added draw_func call with size when dealing with a point layer.
+
+	* Extensions/svgexport/__init__.py: bumped version to 0.9.2.
+	
+2004-12-11  Bernhard Reiter <bernhard at intevation.de>
+
+	Made sure that newlines are inserted in the svg path d attributes
+	to raise the chance that the line length will be below 255 characters,
+	as recommended by REC SVG 1.1 in section 8.3.1.
+
+	* Extensions/svgexport/svgmapwriter.py(DrawPolygon):
+	Adding \n before L's and changed whitespace handling.
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	Adapted tests to new whitespace handling of DrawPolygon.
+
+2004-12-11  Bernhard Reiter <bernhard at intevation.de>
+
+	* Doc/technotes/coding_guidelines.txt: easy typo fixed. 
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	Removed test_drawbezier in favour of new test_drawspline3 and 
+	test_drawspline4 within new class TestDrawSplines(TestVirtualDC).
+	All only to test DrawSpline.
+
+	* Extensions/svgexport/svgmapwriter.py(DrawSpline):
+	New implementation now really using the strange algorithm of
+	xfig 3.1's approximated splines and its conversion to postscript
+	with one twist: SVG can do quadratic beziers, so skipped translation
+	to cubic beziers.
+	(TestWithDC): Typo in comment fixed.
+
+2004-12-09  Martin Schulze  <joey at infodrom.org>
+
+	* Thuban/Model/classgen.py: Added missing character encoding
+
+	* Extensions/wms/properties.py (OpenWMSProperties): removed
+
+	* Extensions/wms/parser.py (WMSCapabilitiesParser.error): Dropped
+	support for get_srs_discrepancies() since there are no
+	discrepancies anymore (was a thinko)
+
+	* Extensions/wms/layer.py (WMSLayer.GetMapImg): Improved graphic
+	format priority now that more formats are supported globally by
+	the render engine. 
+
+2004-12-08  Silke Reimer <silke at intevation.de>
+	* Extensions/ogr/ogrshapes.py: Substituted ogr-method CloseRings
+	because it is not available in all versions of ogr
+
+2004-12-08  Bernhard Reiter <bernhard at intevation.de>
+	* Extensions/ogr/__init__.py: Added empty __init__.py to heal 
+	global tests until a real one is commited.
+
+2004-12-07 Nina Hüffmeyer <nhueffme at intevation.de>
+
+	* /Extensions/ogr/: Adding a new extension to read shapefiles with
+	ogr. It is planned to add other vector formats.
+
+	* /test/runtests.py: Adding tests from /Extensions/ogr/test/.
+
+2004-12-07  Jan-Oliver Wagner <jan at intevation.de>
+
+	* /Extensions/svgexport/test/test_svgmapwriter.py: Reverting
+	part of a (non-)fix to renable that the tests are always
+	executed.
+
+2004-12-07  Bernhard Reiter <bernhard at intevation.de>
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	Added test_drawbezier() to test DrawSpline().
+
+	* Extensions/svgexport/svgmapwriter.py(DrawSpline):
+	Really implemented bezier drawing.
+
+	* Extensions/svgexport/__init__.py: Bumped version of svgexport
+	to 0.9.1 because now the legend examples lines styles 
+	will be drawing with beziers.
+
+2004-12-05  Martin Schulze  <joey at infodrom.org>
+
+	* Thuban/UI/renderer.py (raster_format_map): Added PNG, TIFF and
+	GIF as supported bitmap image formats (helpful for the WMS extension)
+
+2004-11-30  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/test/test_ogclib.py (TestOGCLib.test_compareURLs):
+	Improved the test for the internal compare method
+
+2004-11-27  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/about.py (About.__init__): Added
+	Norbert Solymosi for hungarian translation and Ole Rahn
+	as contributor. Moved Bernhard Reiter from Contributor
+	to Developer.
+
+2004-11-27  Bernhard Reiter <bernhard at intevation.de>
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	Removed Jan from author list as he did not change enough significant
+	lines yet.
+
+	* Extensions/svgexport/__init__.py: Added Bernhard as author
+	of the Extension.
+
+2004-11-27  Jan-Oliver Wagner <jan at intevation.de>
+
+	* po/hu.po: New. Hungarian translation. Contributed
+	by Norbert Solymosi.
+
+2004-11-26  Bernhard Herzog  <bh at intevation.de>
+
+	* Extensions/svgexport/test/test_svgmapwriter.py
+	(Testobjectexport.test_transparent_polygon): Commented out some
+	debug prints
+
+2004-11-24  Jan-Oliver Wagner <jan at intevation.de>
+
+	Fix broken tests for svg extension and added svg legend
+	to Experimental menu.
+
+	* Extensions/svgexport/test/test_svgmapwriter.py: Fix to have
+	the test run correctly even if the extension is a package.
+	Also removed the "import Thuban" which makes no sense.
+
+	* Extensions/svgexport/__init__.py: Fix to have the extensions'
+	test module also be executed from the global test routine.
+	This is done by looking for the absense of the DISPLAY variable.
+
+	* Extensions/svgexport/maplegend.py: Moved the menu entry from Extensions
+	to Experimental menu since this module has yet not reached a stable
+	status (ie. 1.0).
+
+2004-11-22  Bernhard Reiter <bernhard at intevation.de>
+
+	* Extensions/svgexport/svgmapwriter.py:
+	Added verbose variable and some logging depending on it.
+	(class VirtualDC(XMLWriter)): Minor improvement in the polygon loop, 
+	because counting i is not necessary.
+	(class Pen, class Brush): Added simple __str__ methods.
+	(SVGRenderer.draw_polygone_shape): Fix #2698 (transparent polygons are
+	not exported to svg file) Note: holes still unhandled.
+
+	* Extensions/svgexport/test/test_svgmapwriter.py:
+	        Made a baseclass TestWithDC for test needed a DC.
+		Added tests for bug #2698 (transparent polygons are not
+		exported to svg file):
+		Testobjectexport.test_transparent_polygon()
+
+	* Thuban/Model/base.py (UnsetModified):
+	Fixed some typos in docstring.
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.draw_polygon_shape()):
+	Added hints on the used algorithm for handling holes.
+
+2004-11-20  Jan-Oliver Wagner <jan at intevation.de>
+
+	Some face lifting for the examples.
+
+	* Examples/__init__.py: Make this directory a package.
+
+	* Examples/simple_extensions/__init__.py: Make this directory a package.
+
+	* Examples/simple_extensions/hello_world.py: Moved entry from Extensions
+	menu to Examples menu.
+
+	* Examples/simple_extensions/simple_command.py: Some more comments,
+	minor changes.
+
+	* Examples/simple_extensions/simple_tool.py: Minor changes.
+
+2004-11-20  Jan-Oliver Wagner <jan at intevation.de>
+
+	Changed way of extension registry for wms and added extension
+	registry for umn_mapserver extension.
+
+	* Extensions/wms/__init__.py: Added registry entry and the importing
+	of the actual wms module. Included a test for the required PyOGCLib.
+
+	* Extensions/wms/wms.py: Removed registry entry (moved to __init__.py).
+
+	* Extensions/umn_mapserver/__init__.py: Added registry entry and the
+	importing of the actual umn mapserver management modules.
+	Included a test for the required Python MapScript.
+
+2004-11-20  Jan-Oliver Wagner <jan at intevation.de>
+
+	Changed way of extension registry for importAPR, bboxdump
+	and added extension registry for svgexport.extension registry for
+	svgexport.
+
+	* Extensions/importAPR/__init__.py: Added registry entry and the importing
+	of the actual importAPR module.
+
+	* Extensions/importAPR/importAPR.py: Removed registry entry (moved to
+	__init__.py).
+
+	* Extensions/bboxdump/__init__.py: Added registry entry and the importing
+	»···of the actual bboxdump module.
+
+	* Extensions/bboxdump/bboxdump.py: Removed registry entry (moved to
+	»···__init__.py).
+
+	* Extensions/svgexport/__init__.py: Added registry entry and the importing
+	of the svgsaver module.
+
+	* Extensions/svgexport/svgsaver.py: Moved the menu entry from Extensions
+	to Experimental menu since this module has yet not reached a stable
+	status (ie. 1.0).
+
+2004-11-18  Jan-Oliver Wagner <jan at intevation.de>
+
+	Now the hit test considers the size of point symbols.
+
+	* Thuban/UI/viewport.py (ViewPort._hit_point): Added optional parameter
+	'size' defaulting to the previously fixed value 5.
+	Extended doc-string.
+	(Viewport._find_shape_in_layer): Resolved FIXME regarding flexibility
+	for symbols.
+	Now the size of the largest point symbol is determined to find out
+	about whether the point has been hit.
+	This fixes the problem that only clicks inside a fixed distance of
+	5 where found.
+
+2004-11-17  Jan-Oliver Wagner <jan at intevation.de>
+
+	Another open issue fixed regarding sizeable symbols: correct rendering of
+	selected symbols.
+
+	* Thuban/UI/renderer.py (ScreenRenderer.draw_selection_incrementally):
+	Added consideration of the specific size of point symbols.
+	The property for each point symbol is retrieved and the size applied
+	for the rendering method.
+	Added doc-string.
+
+2004-11-16  Jan-Oliver Wagner <jan at intevation.de>
+
+	Changed way of Extension Registry for gns2shp and profiling.
+
+	* Extensions/gns2shp/gns2shp.py: Removed registry entry (moved to
+	__init__.py).
+
+	* Extensions/gns2shp/__init__.py: Added registry entry and the importing
+	of the actual gns2shp module.
+
+	* Extensions/profiling/profiling.py: Removed registry entry (moved to
+	__init__.py).
+
+	* Extensions/profiling/__init__.py: Added registry entry and the importing
+	of the actual profiling module.
+
+2004-10-28  Bernhard Reiter <bernhard at intevation.de>
+
+	* Extensions/svgexport/: Minor improvements to doc strings.
+
+2004-10-07  Jan-Oliver Wagner <jan at intevation.de>
+
+	Further elements for sizable point objects now
+	making this feature usable though not yet complete.
+
+	* Thuban/Model/save.py (SessionSaver.write_classification): Write
+	attribute 'size' for cldata when the shape layer is of point type.
+	This also now make the test_load.py tests happy.
+
+	* Thuban/Model/classgen.py (CustomRamp.GetProperties): Added size
+	gradient.
+
+	* Thuban/UI/classifier.py (ID_SELPROP_SPINCTRL): Renamed to
+	ID_SELPROP_SPINCTRL_LINEWIDTH.
+	(ID_SELPROP_SPINCTRL_LINEWIDTH): New Id replaces ID_SELPROP_SPINCTRL.
+	(ID_SELPROP_SPINCTRL_SIZE): New Id.
+	(SelectPropertiesDialog.__init__): Added a second spin control
+	for the size in case the corresponding layer is of point type.
+	(SelectPropertiesDialog._OnSpin): Renamed to _OnSpinLineWidth.
+	(SelectPropertiesDialog._OnSpinLineWidth): New. Former _OnSpin.
+	(SelectPropertiesDialog._OnSpinSize): New. Set size of property
+	and refresh preview.
+
+
+
+2004-10-04  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/test/test_parser.py
+	(TestWMSCapabilitiesParser.test_compareLists): Added missing
+	self-test for compareLists()
+	(TestWMSCapabilitiesParser.test_compareDicts): Added missing
+	self-test for compareDicts()
+	(TestWMSCapabilitiesParser.test_compareLists): Adding more tests
+	to verify the test routine fails with non-equal arguments 
+	(TestWMSCapabilitiesParser.test_compareDicts): Adding more tests
+	to verify the test routine fails with non-equal arguments 
+
+2004-10-03  Jan-Oliver Wagner <jan at intevation.de>
+
+	First elements for sizeable point objects.
+
+	* Resources/XML/thuban-1.1.dtd: Added size attribute to cldata.
+
+	* Data/iceland_sample_size.thuban: New. Sample for sized point objects.
+
+	* test/test_load.py (ClassificationTest.TestLayers): Added SetSize in case
+	of a corresponding argument is given.
+	(TestSymbolSize): New. Test the size attribute of cldata.
+
+	* Thuban/Model/classification.py: Removed some trailing whitespaces.
+	(ClassGroupProperties.__init__): Set default size.
+	(ClassGroupProperties.SetProperties): Set the size.
+	(ClassGroupProperties.GetSize): New. Return the size.
+	(ClassGroupProperties.SetSize): New. Set the size.
+	(ClassGroupProperties__eq__): Compare also size.
+	(ClassGroupProperties__repr__): Print also size.
+
+	* Thuban/Model/load.py (SessionLoader.start_cldata): Also parse
+	the size attribute.
+
+	* Thuban/UI/classifier.py (ClassDataPreviewer.Draw): Added doc-string.
+	Also, now there is a return value that indicates whether the drawing
+	size exceeded the given rect extent and if so the new extent.
+	Finally, point objects are drawn depending on the size. If either
+	the width or height is exceeded, the new extent is returned.
+	(ClassRenderer.Draw): Now when calling the previewer drawing function,
+	evaluate the return value and, if not None, adapt the grid widget size
+	accordingly and redraw again.
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.draw_shape_layer_incrementally):
+	If the draw function is for points, call it with the size as additional
+	parameter.
+	(BaseRenderer.draw_point_shape): Added additional, optional parameter for
+	the size. Compute the radius using the size.
+
+	* Extensions/importAPR/apr.py (APR_BMkSym.GetThubanProp): Now
+	that Thuban supports size, apply this correctly.
+
+	* Extensions/importAPR/importAPR.py: Bumped version to 0.1.1.
+
+2004-10-03  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual-de.xml: Started translation of
+	Map chapter.
+
+2004-10-01  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/properties.py (wmsProperties.__init__): Extended
+	argument for general use through properties-dialog selector
+	
+	* Thuban/UI/classifier.py: Register properties dialog classes for
+	both provided layer classes/types.
+
+	* Thuban/UI/mainwindow.py (MainWindow.OpenLayerProperties): The
+	map can be retrieved through the parent which is passed to the
+	constructor anyway and doesn't require an argument of its own,
+	required for the unification of arguments for general use through
+	properties-dialog selector.
+	(MainWindow.OpenOrRaiseDialog): Move the logic for checking
+	whether a dialog is already opened (and raising it to the users
+	attention) and creating a new dialog into a function of its own
+	(MainWindow.OpenLayerProperties): Use the new OpenOrRaiseDialog()
+	method
+	(MainWindow.OpenLayerProperties): Utilise the new ClassMapper for
+	global registration of properties dialog classes (which are indeed
+	layer-specific).
+
+	* Thuban/UI/classifier.py (Classifier.__init__): Unify arguments
+	for general use through properties-dialog selector, the map can be
+	retrieved through the parent and doesn't require an argument of
+	its own.
+
+	* Extensions/wms/wms.py: Register the properties dialog class for
+	the provided WMS layer
+
+2004-09-28  Jan-Oliver Wagner <jan at intevation.de>
+
+	New feature: Registry for Extensions.
+
+	* Thuban/UI/extensionregistry.py: This module defines a registry for
+	Extensions.
+
+	* Thuban/UI/about.py (About.__init__): Added description
+	of the registered extensions with all of the information.
+
+	* Thuban/Model/extension.py (Extension): Improved doc-string.
+
+	* Extensions/gns2shp/gns2shp.py, Extensions/importAPR/importAPR.py,
+	Extensions/bboxdump/bboxdump.py, Extensions/profiling/profiling.py,
+	Extensions/wms/wms.py: Added registration of the extension.
+
+2004-09-27  Bernhard Reiter <bernhard at intevation.de>
+
+	More fixes to svgexport to make used ids unique and
+	conforming to XML's Name production. 
+
+	* Extensions/svgexport/test/test_svgmapwriter.py: Added new tests
+	test_xml_id_constraints(), test_make_ide_nosetbaseid() and
+	test_make_id_nonintegersetid().  Switched SetID and SetBaseID.
+	Added Bernhard R. as author.
+	* Extensions/svgexport/svgmapwriter.py (make_id): Using "_" as
+	concatenation char now (makes test_make_ide_nosetbaseid() valid).
+	Also transform second id part with "%d" and catch the TypeError
+	to raise SVGMapWriterError (making test_make_id_nonintegersetid() ok).
+	Corrected typo inBernhard's author line.
+	(SetBaseID): Return the transformed base id. Transform characters
+	which are not alnum() or in ".-_" to binascii.b2a_hex(). Added
+	import binascii. If to be set string starts with "xml" or so, add "t".
+	(draw_shape_layer_incrementally): use the returned value of SetBaseID
+	for used_baseids checks.
+
+2004-09-25  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_layer.py (TestLayer.test_arc_layer_with_projection):
+	Remove a debug print and some tab characters.
+
+2004-09-25  Bernhard Reiter <bernhard at intevation.de>
+
+	* Extensions/svgexport/svgmapwriter.py: Added Bernhard R. as Author.
+	(SetBaseID, SetID, make_id): Improved docstring comments to explain
+	the interaction of the three functions and the XML id contrains.
+
+
+2004-09-23  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/ThubanModel.xmi: New. UML file for Thuban Model
+	Module.
+
+	* Doc/README: Added info on ThubanModel.xmi.
+
+2004-09-23  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/README: New. Some info about how to generate technical
+	documentation from the source code.
+	This text was send to the Thuban developer mailing list on
+	September 21st 2004 by Bernhard Reiter.
+
+2004-09-21  Bernhard Reiter <bernhard at intevation.de>
+
+	Improved the svgexport to only use unique ids. Will issues 
+	an error message dialoge when two layer names are the same.
+	ShapeIDs are now added with a dash within the svg ids.
+
+	* Extensions/svgexport/svgmapwriter.py (SVGMapWriterError): New.
+	* Extensions/svgexport/test/test_svgmapwriter.py: Added imports
+	(TestSVGRenderer): New test class with test_make_in() and
+	test_check_for_layer_name_clash()
+	* Extensions/svgexport/svgmapwriter.py (SVGRenderer): Fixed __init__()
+	and draw_shape_layer_incrementally() to not use a baseid twice, 
+	satisfying test_check_for_layer_name_clash()
+	(VirtualDC.make_id): Use a dash between baseit and id, satisfies
+	test_make_in().
+	* Extensions/svexport/svgsaver.py: Import SVGMapWriterError, wxOK
+	and wxICON_HAND. 
+	(write_to_svg): Put dc and rendering in a try statement and on
+	catching SVGmapWriterError notify the user and delete the target file.
+
+2004-09-20  Bernhard Reiter <bernhard at intevation.de>
+
+	* Model/base.by, Model/layer.py: Fixed typos in docstrings.
+
+2004-09-03  Jan Schüngel  <jschuengel at intevation.de>
+
+	* Extensions/umn_mapserver/mapfile(MF_Class.add_thubanstyle): Fix a
+	small bug with the line color. Now the line color will now only set
+	if it is set in Thuban an not Transparent. 
+	
+	* Extensions/umn_mapserver/mf_export(tblayer_to_map): Fixed a bug with
+	deleting the layers from mapfile. Now all layers will delete backwards 
+	from the last.
+
+2004-08-20  Silke Reimer <silke at intevation.de>
+
+	* Thuban/Model/layer.py:
+	Fixes bug in projection handling: Otherwise very large region might not
+	have valid values in the layer's projection.
+
+2004-08-20  Silke Reimer <silke at intevation.de>
+
+	* Thuban/UI/about.py:
+ 	small changes to be consistent with coding style.
+	  
+2004-08-13  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/test/test_ogclib.py (TestOGCLib.compare_URLs):
+	Adjusted a comment
+
+2004-08-11  Silke Reimer <silke at intevation.de>
+
+	* Thuban/UI/about.py: Small changes to encoding related stuff to avoid
+		too many and too enhanced imports of locale
+
+2004-08-10  Silke Reimer <silke at intevation.de>
+
+	* Thuban/UI/about.py: Fixed encoding problem of about dialog: Added
+		function unicodeToLocale() to convert special characters to users
+		locale encoding
+
+2004-08-10  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/technotes/coding_guidelines.txt: Added rule 'Method names start with
+	lower case letter'
+
+2004-08-09  Jan Schüngel  <jschuengel at intevation.de>
+
+	* ChangeLog: Rewrite the last ChangeLog entry to follow 
+	the standard way.
+
+	* Extensions/umn_mapserver/mapfile: Moved the import AnnotationLayer to
+	the function where it is needed, because it don't works if it stands
+	at the beginning.
+	(MF_Layer.__init__): Removed the extra numclassed variable. Now
+	numclasses from the mapscript will be used.
+	(MF_Layer.get_index): New. Return the index of the layer in mapfile.
+	(MF_Layer.set_classes): New. A Classlist will be set to the layer.
+	(MF_Layer.set_metadata): New. A Metadata mapscript object will set.
+	(MF_Layer.remove_allclasses): New. All class of the layer will remove.
+	(MF_Map.create_new_layer): New. A new Layer is created and associated
+	with the mapscript object.
+	(MF_Map.set_layerorder): New. The Layer order like in thuban is set in
+	the mapscript.
+	(MF_Map.add_thubanlayer): Now a new layerobj is created if no one is
+	linked to the layer in thuban, else the layerobject linked to the
+	thubanlayer will be used.
+	AnnotationLayer will now store the filename of the shapefile.
+	(MF_Map.remove_layer): If a layer is removed the associated object
+	must be set new.
+	
+	* Extensions/umn_mapserver/mf_export.py(tb_layer_to_map): Add all
+	layers which are exists in thuban to the mapobj. All removed Layers
+	will be removed from the mapobj. 
+	Added comments to all functions.
+	(thuban_to_map): No layer will be removed here.
+	
+	* Extensions/umn_mapserver/mf_handle.py
+	(_has_umn_mapobj_and_selectedlayer): Activating the layer menu. Now
+	Layersettings for the mapserver kann be edited.
+
+	* Extensions/umn_mapserver/mf_import.py: Now all layers which are
+	imported, will be linked with the associated MF_Layer.
+	(import_mapfile): All layers, which are not selected, will be removed.
+	Disable the "import layer from mapfile" menu option.
+
+	* Extensions/umn_mapserver/sample/iceland.map: Set the status of the
+	Annotation Layer from DEFAULT to OFF. The DEFAULT setting turns the
+	layer on permanently.
+
+2004-08-03  Jan Schüngel  <jschuengel at intevation.de>
+
+	* Extensions/umn_mapserver/mapfile.py(MF_Metadata.remove_allmetadata):
+	New. This function removes all metadata
+	(MF_Layer.set_group): New. Set the group setting.
+	(MF_Layer.get_group): New. Get the group setting.
+	(MF_Map): Removed the extra numlayers variable, used the mapscript 
+	parameter instead.
+	(MF_Map.get_numlayers): New. This get numlayers.
+	(MF_Map.remove_all_layers): New. Removes all layers from the mapobj.
+	(MF_Map.add_thubanlayer): Replaced the exception handling by a check
+	if the object is an instance. Also added the annotation layer here to
+	export, but only the layer is created in the mapfile.
+
+	* Extensions/umn_mapserver/mf_export.py(export_mapfile): Removed 
+	the check if a mapobj exist, because its not needed anymore. The 
+	export function is only available if a mapobj exist. 
+	Use the new function to remove all layers.
+	
+	* Extensions/umn_mapserver/mf_handle.py(Layer_Dialog): Added a group
+	option and the metadata button.	The layer dialog is temporary disabled.
+	(Metadata_CustomDataTable): Added some functions to show the grid
+	correct.
+
+	* Extensions/umn_mapserver/mf_import.py: Moved the code for showing 
+	the number of layer from import_mapfile to this function.
+	(AnnotationLayer): New. This Class shows the Annotation layer in
+	thuban. The layer don't do anything. It's only to show the layer
+	and to save the layer order.
+	(add_annotationlayer): New. Import an annotation layer to thuban.
+	(select_layer2import): New. Import only layers to thuban and not 
+	the other settings like projection or scalebar.
+	(create_new_mapfile): Moved the _has_umn_mapobj function and the 
+	create_new_mapfile functions from mf_handle.py to mf_import.py.
+	
+	* Extensions/umn_mapserver/sample/iceland.map: Added the group
+	parameter to the roads and cultural layers. Also added a new
+	Annotation Layer for the cultural points.
+
+	* Extensions/umn_mapserver/sample/iceland.html: Added the select
+	option for the annotation layer.
+
+	* Extensions/umn_mapserver/sample/index.html: Added the start
+	parameter for the annotation layer.
+
+2004-08-01  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual-de.xml (Chapter Session Management):
+	translation completed.
+
+	* Doc/manual/thuban-manual.xml (Chapter Session Management):
+	Fixed unprecise description for Save Session.
+
+2004-07-31  Jan-Oliver Wagner <jan at intevation.de>
+
+	Started translation of Users Manual into german.
+
+	* Doc/manual/thuban-manual-de.xml: New. German Users Manual.
+
+	* Doc/manual/Makefile: Added build instructions for german
+	users manual.
+
+	* Doc/manual/thuban-manual.xml: Minor corrections in Introduction.
+
+2004-07-28  Jan Schüngel  <jschuengely at intevation.de>
+
+	* Extensions/umn_mapserver/mapfile.py(MF_Metadata): Changed all class
+	functions. Now all metadata will handle by the function and its not
+	needed to initialize it from outside. Therefor the associated mapobj 
+	will be stored in the Metadata Object. So we can use the special
+	functions from the associated mapobj to get the Metadata.
+	Therefor all initialization code for the metadata is removed from the
+	other classes.
+	(MF_Layer): Added a function to get the metadata object. 
+	(MF_Map): Added a function to set the mappath, the path where
+	the mapfile ist stored.
+
+	* Extensions/umn_mapserver/mf_export.py(thuban_to_map): Changed the code
+	to set the extent in the mapfile. Now the code is set by the displayed
+	data in the Thuban-view.
+	(export_mapfile): The shapepath is now set empty, until relative
+	pathnames are supported.
+
+	* Extension/umn_mapserver/mf_handle.py: Added a dialog to handle
+	metadata. Yet only mapfile metadata are supported. Layer and class
+	supported are not implemented.
+	Added a dialog to handle layer informations. The dialog only shows the
+	selected layer at the moment.
+
+	* Extensions/umn_mapserver/mf_import.py(import_mapfile): Changed the
+	code for setting the extent in thuban. Now the extent is set to the
+	given extent from the mapfile. 
+	Fixed a logical mistake. Now the extent is set when realy a layer is
+	loaded, and not if one is selected to load.
+
+	* Extensions/umn_mapserver/sample/iceland.html: Added code to zoom and
+	move the shown map in the browser.
+
+	* Extensions/umn_mapserver/sample/iceland.map: Added a new metadata
+	line to the mapobj and added metadata to the political layer.
+
+	* Extensions/umn_mapserver/test/test_mapserver.py: Changed the test
+	for Metadata.
+
+2004-07-26  Martin Schulze  <joey at infodrom.org>
+
+	* Thuban/Lib/classmapper.py (ClassMapper.has): Added the new
+	ClassMapper
+
+	* test/test_classmapper.py (TestMapping.test_mapper): Added a Test
+	case for the new ClassMapper
+
+
+2004-07-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/viewport.py (ViewPort.VisibleExtent): New.  Return the
+	visible extent of the map in projected coordinates
+
+	* test/test_viewport.py (SimpleViewPortTest.test_default_size)
+	(SimpleViewPortTest.test_init_with_size): Add some VisibleExtent()
+	tests.
+	(SimpleViewPortTest.test_visible_extent): New. The real test for
+	VisibleExtent()
+
+2004-07-22  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_viewport.py: Use support.run_tests as the main
+	function when running asa script.
+
+2004-07-22  Jan Schüngel <jschuengel at intevation.de>
+
+	* Extensions/umn_mapserver/mf_export.py: Added "import os"
+	Removed the old "import Thuban.UI.mainwindow" code.
+	(tbextent_to_map): Removed the extra function and at the code direct
+	to "thuban_to_map" function.
+	(write_creatorcomment): Added. Now a short comment is added to the
+	beginning of an generated mapfile.
+	(export_mapfile): Now the Path and filename are saved in to variables,
+	and not together in one variable. This is needed for the new
+	write_creatorcomment function.
+		
+	* Extensions/umn_mapserver/mf_import.py (import_mapfile): Added the
+	import module "re". Also added Range and the ClassGroupRange import 
+	from Thuban. Both are needed for the new range expression import.
+	(create_rangeexpression): Added. Creates a Range Expression in Thuban
+	style from a given mapfile expression.
+	(added_rasterlayer): Make some small code changes. The shapepath is
+	now stored in an extra variable and the clazz_name is set empty if no
+	class name set in the mapfile.
+	Changed the Error message for Range Expressions, becaus the new
+	function create a error string which will be shown in the dialog.
+
+	* Extensions/umn_mapserver/test/test_mapserver.py: Added a test for the
+	range expression import.
+
+2004-07-21  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Extensions/umn_mapserver/README: Added hint that
+	installation as root can be avoided. Removed all tabs.
+
+2004-07-16  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_viewport.py
+	(ViewPortTest.test_changing_map_projection): Check that changing
+	the projection of an empty map shown in a viewport doesn't lead to
+	exceptions in the viewport's handler for the
+	MAP_PROJECTION_CHANGED messages
+
+	* Thuban/UI/viewport.py (ViewPort.map_projection_changed): Only
+	try to keep the same region visible when the map actually contains
+	something
+
+2004-07-15  Jan Schüngel <jschuengel at intevation.de>
+
+	* Extensions/umn_mapserver/mapfile.py: Added a function to get the
+	mappath directly from the mapobj. Is needed because of the changes 
+	in mf_import.py.
+	(MF_Layer.add_thubanclass): Added a new comment.
+	(MF_Map.set_extent): Fixed a bug with exporting empty mapobj. If the
+	mapobj is empty there is no extent get from thuban an so no one can
+	set to th mapobj.
+	
+	* Extensions/umn_mapserver/mf_import.py (import_mapfile): Updated
+	the discription. 
+	Split the funktion in to three smaller ones. The new functions are 
+	add_rasterlayer, add_polygonlayer and select_layer2import.
+	Removed the mapfilepath and filepath initialisation, because its know
+	include in the new functions.
+	Now nothing will be imported if cancel is pressed in the
+	layer choice dialog.
+
+2004-07-14  Jan Schüngel <jschuengel at intevation.de>
+
+	* Extensions/umn_mapserver/mapfile.py: Added ClassGroupDefault to
+	import.
+	(MF_Symbolset): Removed the extra variable for numsymbols.
+	(MF_Class.__init__): Added a comment to the exception clause.
+	Removed the extent init, because it was not needed anymore.
+	(MF_Layer.add_thubanclass): Added the code to set the class name to
+	the expression value from thuban if no label is defined. 
+	Added the code to export Range expressions from thuban to the mapfile.
+	(MF_Map.set_extent): Removed the exception and replace it by some if
+	code. If the size of a map is not defined the size will be set to 1,1.
+	This is necessary because if the extent is set, mapscript checks if
+	the size is greater than zero.
+	(MF_Web): Added the get and set function for the template.
+
+	* Extensions/umn_mapserver/mf_export.py: Added the function to check
+	if a mapobject exists and used it to set the status of the menu items.
+	If no mapfile exists the settings could not be edditied. 
+	Define after which menuitem the exportitem will include.
+	
+	* Extensions/umn_mapserver/mf_handle.py: Removed the import 
+	Thuban.UI.mainwindow clause, because it is not needed.
+	Added the command Refresh() to all "OnChangeColor()" functions,
+	because the color preview window was not updated on a color change.
+	Added the function to check if a mapobject exists and used it to set the
+	status of the menu items. If no mapobject exists the settings could not
+	be edditied.
+	(Map_Dialog): Moved the imagetype selector from the
+	Outputformat_Dialog to Map_Dialog and removed Outputformat_Dialog.
+	(Web_Dialog): Removed the name label and added the template textbox.
+
+	* Extensions/umn_mapserver/mf_import.py (import_mapfile): Replace
+	the exception handling on loading the layers by an if statement. It
+	is not necessary to us the exception there.
+	The Filepath creation now use os.path.join to build the path.
+
+	* Extensions/umn_mapserver/test/test_mapserver.py: Moved the testMap
+	definition from global to the setUp function. Now the testMap will
+	initialize new on each test.
+
+	* Extensions/umn_mapserver/sample/iceland.map: Include three new
+	classes in the Line Layer, to test logical Expressions.
+	Set the status of the class "Point9" in the Point Layer to off
+	
+2004-07-13  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/baserenderer.py
+	(BaseRenderer.render_map_incrementally): Fix a logic bug in the
+	optimization that tries not to draw layers under a raster layer.
+	The bug was harmless.  All it effectively did was to produce The a
+	strange messages about not being able to draw Layer instances for
+	all vector layers below a raster layer which would be invisible
+	anyway because the raster layer currently always covers the entire
+	window
+
+2004-07-08  Jan Schüngel <jschuengel at intevation.de>
+
+	* Extensions/umn_mapserver/mapfile.py: Added code to generade and get
+	a list of supported outputformats. This formats are not alle supported
+	because there is no possibility to get the outputformat without the
+	name known. Make some formal changes to the code.
+	(MF_Map.set_name()): Fixed a bug if the name is None.
+
+	* Extensions/umn_mapserver/mf_handle.py: Removed the image_type import
+	statement, because its not needed anymore. The Outputformat is now
+	given as string from the object. Make some formal changes to the code.
+
+	* Extensions/umn_mapserver/test/test_mapserver.py: Added new test for
+	most of the new setting which were added during the last changes.
+	Removed the MF_Size Test.
+	
+	* Extensions/umn_mapserver/test/test.map: Added a new class to the
+	cultural Layer to test expressions and the the status of that layer
+	from on to default.
+	Changed the data path the the correct Thuban Data
+	Added the Outputformat Object and Symbol Object
+	
+2004-07-07  Jan Schüngel <jschuengel at intevation.de>
+
+	* Extensions/umn_mapserver/mapfile.py: Added some new
+	settings to edit (outputformat, label, imagetype)
+
+	* Extensions/umn_mapserver/mf_handle.py: Added some setting to
+	the Label Dialog and add the OutputDialog.
+	Make some changes to the code order.
+
+2004-07-06  Jan Schüngel <jschuengel at intevation.de>
+
+	* Extensions/umn_mapserver/mapfile.py: Added the symbolObj, pointObj
+	and line Obj and add the scalebar_status_type, scalebar_style_type and
+	scalebar_position_type.
+	Added the symbol- and symbolsetObject (MF_Symbol,MF_Symbolset). The
+	are only used to create a Symbol like the circle in Thuban.
+	Added the scalebarObject (MF_Scalebar)
+	(MF_Class): Added set_status and get_status.
+	(MF_Layer.add_thubanclass): Added code to set the class status
+	(MF_Map): Added code to handle the symbols and scalebar 
+	(MF_Label): Added the set_partials and get_partials functions
+	
+	* Extensions/umn_mapserver/mf_export.py: Added MF_Symbol to import
+	from mapfile. Added a function to create a circle object like the one
+	from thuban if no one exists.
+	
+	* Extensions/umn_mapserver/mf_handle.py: All colors are now set when
+	press ok in the assosiated dialog and not at the end of the
+	colordialog.
+	Added the Dialog for the Scalebar.
+	(Label_Dialog): Added the offset option
+
+	* Extensions/umn_mapserver/mf_import.py: Added code to import the
+	status of the Classes.
+	Fixed a bug with the projection. Now the to_meter parameter will be
+	added to the Projection only if it doesn't exists. 
+
+2004-07-01  Jan Schüngel <jschuengel at intevation.de>
+
+	Added the functionality to handle the content thuban is not
+	able to handle directly.
+
+	* Extensions/umn_mapserver/mf_handle.py: New. This module extents
+	Thuban with the possibility to edit the mapfile content.	
+	
+	* Extensions/umn_mapserver/mf_import.py: Added the possibility
+	to import mapfiles without any layer selected. So it is possible 
+	to edit the other settings in a mapfile.
+	(import_mapfile): Added code to use the editing functions.
+	Added the possibility to import the projection to a layer if one
+	is defined.
+	Status settings (On,Off) will now set in thuban (visible, invisible).
+	fixed a bug with with classnames. If no classname is set in mapfile
+	the value in Thuban will set to the expression.
+	
+	* Extensions/umn_mapserver/mf_export.py(export_mapfile): Added the
+	possibility to save a new mapfile or use the old one which is 
+	imported or new created.
+	Added code to use the editing functions.
+	Remove some not needed import statements
+
+	* Extensions/umn_mapserver/mapfile.py: Added new types which are
+	need for the editing functions.
+	Added needed set-functions for the editing functions.
+	Added the possibility to export rasterimages.
+	Added new classes (MF_Web, MF_Label, MF_Legend, MF_Symbol,
+	MF_SymbolSet). MF_Symbol and MF_SymbolSet are not needed at the
+	moment.
+	(MF_Class.set_thubanstyle): Now point layers will set to a default
+	symbol to show a circle in mapserver and not only a 1px dot.
+	(MF_Style.__init__): Fixed a bug with the color. Color was not set
+	correct before.
+	(MF_Size): Removed, because it is not needed.
+	
+	* Extensions/umn_mapserver/README: Added the hints to use the
+	export and editing functions, too.
+
+	* Extensions/umn_mapserver/sample/iceland.map: Added the
+	new parameter "UNITS METERS".
+	Change the political layer to status OFF.
+
+	* Extensions/umn_mapserver/sample/README: Added some
+	more details to setup the sample in the MapServer.
+	
+2004-06-26  Bernhard Reiter <bernhard at intevation.de>
+
+	* Extensions/svgexport/test/test_svgmapwriter.py: 
+	Removed class VFile and used standard StringIO instead.
+
+2004-06-23  Jan Schüngel  <jschuengel at intevation.de>
+
+	Add the export function to the umn_mapserver extension.
+
+	* Extension/umn_mapserver/mf_export.py: New. This module extents
+	Thuban with the possibility to export the Thuban content.
+
+	* Extensions/umn_mapserver/mapfile.py: Expand the classes to use
+	with the export module. Especially added the possibility to
+	add thuban objects directly to the map objects.
+
+	* Extensions/umn_mapserver/mf_import.py: Removed the wxCHANGE_DIR,
+	because of the hint from Bernhard Herzog.
+	Corrected the handling of absolute pathnames.
+	Changed the Text of the Menu-Item, now the beginning is upper case.
+
+	* Extensions/umn_mapserver/README: Added the --with-tiff statement.
+
+2004-06-16  Jan Schüngel  <jschuengel at intevation.de>
+
+	Add a sample and make some changes.
+
+	* Extension/umn_mapserver/mf_import.py: Changed the wxPython.wx
+	import from * to explicit used statements. Changed the 
+	Thuban.UI.mainwindow import phrase, too.
+	(import_mapfile):Corrected a clerical mistake.
+	Added wxCHANGE_DIR in OpenFile Dialog.
+	Added a MultipleChoiceDialog, to select the layers to load from
+	mapfile into thuban. Thereby the projection is only set if one layer
+	is selected.
+	Added the possibility to handle relative pathnames which uses 
+	up-level references.
+	Removed some doubled code.
+	Corrected an error with integer values used as label in thuban
+	ClassGroup.
+	
+	* Extensions/umn_mapserver/sample: New.
+
+	* Extensions/umn_mapserver/sample/README: New. Describes the
+	usage of the sample files.
+
+	* Extensions/umn_mapserver/sample/iceland.map: New. This is
+	a suitable .map-file for the iceland data. 
+
+	* Extensions/umn_mapserver/sample/index.html: New. The template
+	for the mapfile.  
+
+	* Extensions/umn_mapserver/sample/iceland.html: New. Initialisation
+	file for the Iceland Application on web.
+
+	* Extensions/umn_mapserver/README: Corrected a inaccuracy and added
+	some details.
+
+	* Extensions/umn_mapserver/test/test_mapserver
+	(mapserver_import_Test_generalClasses.test_MF_Color):
+	Corrected the thubancolor test.
+
+2004-06-15  Jan Schüngel  <jschuengel at intevation.de>
+
+	* Extensions/umn_mapserver/README: New. Install instruction.
+
+2004-06-14  Bernhard Reiter <bernhard at intevation.de>
+
+	* libraries/thuban/cpl_mfile.h: Added copyright header.
+
+	* libraries/thuban/ cpl_mfile.cpp, cpl_mfile.h: Added non-protecting
+	Free Software License so that it is most useful with gdalwarp 
+	and bmpdataset.
+
+2004-06-14  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/multiplechoicedialog.py (__version__): Add missing
+	import of wxPython.wx itself (as opposed to the contents of
+	wxPython.wx).  For some reason wxPython.wx is available as
+	wxPython.wx.wx in at least some 2.4 releases.  Fixes RT#2482
+	wrt. wxPython 2.4.
+
+2004-06-10  Jan Schüngel  <jschuengel at intevation.de>
+
+	Initial version of new extension "umn_mapserver".  This extension aims
+	to manage configuration for the UMN MapServer application.  This
+	inital version just imports the .map-files and displays all, Thuban is
+	capable of.
+
+	* Extensions/umn_mapserver, Extensions/umn_mapserver/test: New.
+
+	* Extensions/umn_mapserver/test/README: New. Describes how to run the
+	tests.
+
+	* Extensions/umn_mapserver/test/test.map: New. This is a test
+	.map-file for automated tests of the umn_mapserver extension of
+	Thuban.
+
+	* Extensions/umn_mapserver/test/test_mapserver.py: New. Tests for
+	UMN Mapserver classes.
+
+	* Extensions/umn_mapserver/__init__.py: New. Init to make this
+	directory a package.
+
+	* Extensions/umn_mapserver/mapfile.py: New. Classes to represent
+	'.map'-file objects.
+
+	* Extensions/umn_mapserver/mf_import.py: New. This module extends
+	Thuban with the possibility to handle UMN MapServer mapfiles.
+
+2004-06-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.TreeInfo): Convert the bounding box
+	to a tuple before using it as arguments to the % operator.  This
+	fixes the formatting issue filed in RT#2239 on 2004-01-13 and
+	reported today on thuban-list by Jan Schüngel
+
+	* test/test_layer.py (TestLayerModification.setUp): Save the
+	filename as an instance variable so we can refer to it in tests
+	(TestLayerModification.test_tree_info): Uncomment this method
+	again and make it work.  This tests for the formatting issue
+	filed in RT#2239 on 2004-01-13
+
+2004-05-28  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/baserenderer.py: Fix some typos.
+
+2004-05-18  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Extensions/gns2shp/gns2shp.py (gns2shp): Fixed a bug
+	by increasing a field size.
+
+2004-05-17  Bernhard Herzog  <bh at intevation.de>
+
+	Update to newest shapelib and get rid of Thuban specific
+	extensions, i.e. use the new DBFUpdateHeader instead of our
+	DBFCommit kludge
+
+	* libraries/shapelib/shpopen.c: Update to version from current
+	shapelib CVS.
+
+	* libraries/shapelib/shapefil.h: Update to version from current
+	shapelib CVS.
+
+	* libraries/shapelib/dbfopen.c: Update to version from current
+	shapelib CVS.
+	(DBFCommit): Effectively removed since shapelib itself has
+	DBFUpdateHeader now which is better for what DBFCommit wanted to
+	achieve.  
+	We're now using an unmodified version of dbfopen.
+
+	* setup.py (extensions): Add the HAVE_UPDATE_HEADER macro with
+	value '1' to the Lib.dbflibc extension.  This simply reflects the
+	shapelib and pyshapelib updates
+
+2004-05-16  Jan-Oliver Wagner <jan at intevation.de>
+
+	Finished introduction of Menu.FindOrInsertMenu.
+
+	* Extensions/drawshape/drawshape.py: Add the command
+	to the experimental menu additionally to the toolbar.
+
+	* Extensions/svgexport/svgsaver.py: Use FindOrInsertMenu() instead of
+	finding menu on its own.
+
+	* Doc/manual/thuban-manual.xml: updated sample file
+	to use FindOrInsertMenu().
+
+	* Examples/simple_extensions/hello_world.py: Use FindOrInsertMenu()
+	instead of finding menu on its own.
+
+2004-05-11  Jan-Oliver Wagner <jan at intevation.de>
+
+	* test/test_menu.py (MenuTest.test): Added testing
+	of method Menu.FindOrInsertMenu.
+
+2004-05-10  Jan-Oliver Wagner <jan at intevation.de>
+
+	Introduce and use Menu.FindOrInsertMenu.
+
+	* Thuban/UI/menu.py (Menu.FindOrInsertMenu): New. Find a
+	  given menu or, if not found, insert it.
+
+	* Extensions/bboxdump/bboxdump.py, /Extensions/gns2shp/gns2shp.py,
+	/Extensions/importAPR/importAPR.py, Extensions/profiling/profiling.py,
+	/Extensions/wms/wms.py: Use FindOrInsertMenu() instead of finding
+	menu on its own.
+
+2004-05-06  Jan-Oliver Wagner <jan at intevation.de>
+
+	Introduce a abstract ColorDialog class and remove
+	and outdated file.
+
+	* Thuban/UI/proj4dialog.py: Removed. It is has been
+	replaced by projdialog for quite a while and is not used
+	anymore.
+
+	* Thuban/UI/colordialog.py: New. Abstraction for color selection
+	dialog(s).
+
+	* Thuban/UI/classifier.py (SelectPropertiesDialog.__GetColor):
+	Now calls the abstract ColorDialog instead of wxColourDialog.
+	This also removed the dependency to Color class conversion
+	from this function.
+
+2004-05-04  Frank Koormann  <frank at intevation.de>
+
+	* Extensions/bboxdump/__init__.py: Fixed string left over from 
+	copying.
+
+	* Extensions/bboxdump/bboxdump.py (bboxdump): 
+	Use layer.ShapeStore().AllShapes() to loop over shapes instead of 
+	xrange(layer.NumShapes()). Compile the bboxmessage from a list 
+	of formatted outputs (string.join) instead of appending to the
+	message. Two progress bar dialogs to report progress on the sometimes
+	lenghty processing.
+
+2004-04-22  Frank Koormann  <frank at intevation.de>
+
+	New Extension to dump bounding boxes of all shapes of the selected 
+	layer. An optional column can be specified to group the objects, 
+	in this case the bounding box is a union of the separate boxes.
+	Dump can be displayed in a ScrolledMessageDialog or written to file. 
+	The Extension is simply a combination of available and well tested
+	Thuban functionality.
+
+	* Extensions/bboxdump/__init__.py: New: Init to make this
+	directory a package.
+
+	* Extensions/bboxdump/bboxdump.py: New: Dump bounding boxes of 
+	all shapes of the selected layer.
+
+2004-04-22  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/classgen.py (GenUniquePanel.__init__): Fixed two
+	strings to be i18n now.
+
+2004-04-18  Jan-Oliver Wagner <jan at intevation.de>
+
+	Changing popup menu of legend from direct building
+	to using the Menu construction as used for the mainwindow.
+
+	* Thuban/UI/mainwindow.py: New method commands: layer_to_top,
+	layer_to_bottom, layer_visibility
+	(MainWindow.LayerToTop): New. Put current layer to the top.
+	(MainWindow.LayerToBottom): New. Put current layer to bottom.
+	(MainWindow.HideLayer, MainWindow.ShowLayer, _has_visible_map):
+	Replace 1,0 by True, False.
+	(MainWindow.ToggleLayerVisibility): New. Toggle visibility of
+	current layer.
+	(MainWindow.LayerShowTable): Removed raising of dialog.
+	(_has_selected_layer_visible): New. Support function.
+
+	* Thuban/UI/legend.py: ID_POP_xxx: removed.
+	(LegendPanel.__init__): Removed EVT_MENU bindings.
+	(LegendTree._OnRightClick): Replace direct creation of
+	menu via wx Classes by applying the menu definition
+	as of Menu class of menu.py.
+	
+2004-04-16  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/exceptiondialog.py (ExceptionDialog.dialog_layout): Improved
+    button string to stronger clearify that Thuban will be closed when hitting
+	the button.
+
+	* Thuban/UI/mainwindow.py (MainWindow.LayerShowTable): Added docstring.
+	Now for layers without a ShapeStore a corresponding message is given
+	to the user, that this layer has no table to show.
+
+2004-04-15  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/layer.py (WMSLayer.setWMSFormat): Need to
+	recalculate the format for the internal render engine as well.
+
+	* Extensions/wms/properties.py (wmsProperties): First start for a
+	properties dialog.  It's functional for a first selection of
+	layers, but still has some weired wxWidgets/GTK problems but
+	beautification can be done later.
+
+	* Extensions/wms/layer.py: Added more documentation
+	(WMSLayer.getFormats): New: Return list of supported image formats
+	by the WMS server
+	(WMSLayer.getLayers): New: Return the list of layer names
+	supported by the WMS server
+	(WMSLayer.getLayerTitle): New: Return the title of the named layer
+	(WMSLayer.getWMSFormat): New: Return the image format that is used
+	for WMS GetMap requests
+	(WMSLayer.setWMSFormat): New: Set the image format that is used
+	for WMS GetMap requests
+	(WMSLayer.__init__): Move away from using only one layer to using
+	a list of layers (unsorted at the moment, though).
+	(WMSLayer.getVisibleLayers): New: Return the list of names for all
+	visible layers
+	(WMSLayer.setVisibleLayers): New: Set the list of names for all
+	visible layers
+
+	* Extensions/wms/wms.py: Moved the WMS layer into layer.py in
+	order to establish a clean structure.
+
+	* Extensions/wms/layer.py: Moved the WMS layer into a file on its
+	own in order to establish a clean structure.
+
+2004-04-13  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/parser.py (WMSCapabilitiesParser.grok): Added
+	support for oldstyle (WMS 1.0 apparently) image format
+	specification.
+
+	* Extensions/wms/wms.py (WMSLayer.calcFormat): Reduce the list of
+	supported graphic formats back to JPEG and BMP, PNG and others are
+	too *cough* experimental...  Sorry, I meant to filter this out
+	before I committed this part.  This should make the WMS extension
+	run from CVS again.
+	(wms_dialog): Reset an empty URL to None so that the subsequent
+	program can depend on this, since the dialog will indeed return an
+	empty URL, causing another declaration of love by Python.
+
+	* Extensions/wms/parser.py (WMSCapabilitiesParser.getLayerBBox):
+	Whenever a native BoundingBox request cannot be fulfilled, check
+	whether the requested SRS is EPSG:3426, in which case return the
+	LatLonBoundingBox values.
+
+	* Extensions/wms/test/test_parser.py
+	(TestWMSCapabilitiesParser.test_LayerSRS): Added a test for
+	ignoring AUTO:* SRS.
+	(TestWMSCapabilitiesParser.test_LatLonBoundingBoxes_as_bboxes):
+	Added another test method to test whether the LatLonBoundingBox
+	values will be returned if BoundingBox values are requested with
+	SRS set to EPSG:3426.
+
+	* Extensions/wms/parser.py (WMSCapabilitiesParser.peekLayers):
+	Added rudimentary support for non-EPSG SRS, i.e. ignore them for
+	the moment by placing them into a variable which is currently
+	unused.  Also test whether the EPSG SRS is numerical as it should
+	be and add an error message if it is not.
+
+	* Extensions/wms/test/sample.xml: Added AUTO:* SRS since they
+	appear in the real world as well.  Since we cannot handle them yet
+	(OGCLib can't either), we will ignore them for the moment.
+
+	* Extensions/wms/parser.py: Use a variable for denoting the sample
+	filename
+	(WMSCapabilitiesParser.peekLayers): Added support for error
+	messages during grok().  They will be aggregated in an array and
+	may be displayed later.  We may have to add a classification
+	"Warning" and "Error" to this.  That requires more experience,
+	though, since not every error may be lethal.
+
+	* Thuban/UI/mainwindow.py (MainWindow.LayerShowTable): Raise the
+	ShowTable() dialog/frame when the user attempts to display it
+	while it has been opened before already and not closed again.
+
+2004-04-11  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/infodialog.py: Adjusted the class documentation
+
+	* Extensions/wms/wms.py (WMSLayer.__init__, WMSLayer.GetMapImg):
+	Switch to using Thuban{Begin,End}BusyCursor instead of the pure
+	wxWidgets variants.
+	(WMSLayer.__init__): The epsg_id variable is named top_srs now.
+
+	* Extensions/wms/infodialog.py: Added an information dialog that
+	will display various information about the WMS current resource,
+	so that additional information such as the title, the abstract,
+	fees and access constraints can be displayed for the user if they
+	are documented in the WMS XML.
+
+2004-04-10  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/parser.py (WMSCapabilitiesParser.grok): Adjusted
+	string handling.  It's "foo".lower() and not lower(foo) without
+	lower imported from strings or something.
+
+	* Extensions/wms/wms.py (WMSLayer): Incorporated WMSCapabilities
+	from capabilities.py and parser.py.  Implement priority list for
+	supported graphics formats, take care of wbmp != bmp.  PNG, TIFF
+	and GIF are supported here, but not yet by main Thuban.  Hence,
+	support for them may be removed later.  Special contribution to
+	usability: get wxWidgets to change the cursor when we're waiting
+	for data from the network so the user won't start to worry.  This
+	causes a redrawing error/warning, though.
+
+	* Extensions/wms/parser.py (WMSCapabilitiesParser.grok): Unlink
+	the DOM object.
+
+2004-04-01  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/capabilities.py: Adjusted documentation
+	(WMSCapabilities.__init__): Improved documentation, fixed syntax
+	(WMSCapabilities.saveCapabilities): Only catch IOError when
+	handling files
+	(WMSCapabilities.loadCapabilities): Only catch IOError when
+	handling files
+	__main__: corrected variable naming
+	(WMSCapabilities.fetchCapabilities,loadCapabilities): Make this
+	class a specialisation of WMSCapabilitiesParser as well.  Also
+	execute grok() after loading or fetching capabilities, if that
+	went well, so that subsequent calls can already access the data.
+	(WMSCapabilities.getVersion): Export the used version of the
+	GetCapabilities request, so we can use it for subsequent calls,
+	i.e. for GetMap requests.
+	(WMSCapabilities.fetchCapabilities): Added proper error handling
+	when the GetCapabilities request failed, so that the surrounding
+	program can act accordingly.
+
+2004-03-30  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/parser.py (WMSCapabilitiesParser.getLayerSRS):
+	Adjusted the getLayerSRS method to return the list of SRSes
+	extracted from <SRS> elements instead of <BoundingBox> elements.
+	Added a bit of documentation as well.
+	(WMSCapabilitiesParser.checkLayerSRS): Removed integrity test
+	since it was only implemented due to a misunderstanding.
+
+	* Extensions/wms/test/test_parser.py
+	(TestWMSCapabilitiesParser.test_LayerSRS): Adjust the tests to
+	reflect the corrected interpretation of the standard: i.e. a layer
+	does not have to define a BoundingBox for all SRSes it supports.
+	Hence the <SRS></SRS> specification is authoritative, not the list
+	of BoundingBoxes.
+	(TestWMSCapabilitiesParser.test_BoundingBoxes): Added a new test
+	to ensure None is returned for a non-existing SRS.
+	(TestWMSCapabilitiesParser.test_grok): Removed test_grok method
+	since it is not applicable anymore.  Listing more SRSes in <SRS>
+	elements is valid according to the specs.
+
+2004-03-26  Bernhard Reiter <bernhard at intevation.de>
+
+	* README: Nicer formatting of text. Improved descriptions.
+	Reflected wxWidgets name change.
+	
+	* Thuban/UI/about.py: Extended copyright to 2004 and added
+	information about the thuban-devel mailinglist.
+
+2004-03-24  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/capabilities.py: Renamed the class to contain
+	'WMS', also added a linebreak where required
+
+	* Extensions/wms/parser.py: Finally added the XML parser for the
+	GetCapabilities response.
+
+	* Extensions/wms/test/sample.xml: Adjusted the sample file so that
+	<SRS> elements match the <BoundingBox> elements, except for the
+	layer 'beschriftung'.
+
+	* Extensions/wms/test/test_parser.py: Encode non-ascii strings
+	since Python uses unicode strings internally, otherwise
+	comparisons will fail.  Removed tests for getLayerBBoxSRS() since
+	the SRS will be calculated anyway and this method is obsoleted by
+	getLayerSRS().  Denote SRS as strings and not as cardinal numbers.
+	Move loading the sample file into the setUp method.  Added a test
+	for finding the integrity problem in the sample response.
+	Improved formatting.
+
+	* Extensions/wms/domutils.py: Added convenience routines for
+	handling of Document Object Model (DOM) nodes.
+
+	* Extensions/wms/test/test_domutils.py: Added a test for the
+	domutils module
+
+2004-03-19  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/test/test_parser.py (TestWMSCapabilitiesParser):
+	Moved path detection and adding into a module of its own,
+	adjustpath, which exports thubandir as main Thuban directory.
+
+	* Extensions/wms/test/test_ogclib.py (TestWMSLib): Moved path
+	detection and adding into a module of its own, adjustpath, which
+	exports thubandir as main Thuban directory.  Reorganised the
+	module in order to support the SkipTest feature for Thuban test
+	cases.
+
+	* Extensions/wms/test/adjustpath.py: Moved path detection and
+	adding into a module of its own.
+
+2004-03-18  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/test/test_parser.py: Added another test for
+	checking whether the WMS XML parser (to be implemented) returns
+	the information we expect.  This requires a sample WMS WML file
+	(sample.xml) which has been extracted from the frida server and
+	"improved" manually.
+
+	* Extensions/wms/test/test_ogclib.py: Added legacy code to add the
+	main Thuban directory to the path in order to be able to import
+	random modules.  Adjusted the PyOGCLib detection to reuse the
+	information gathered.  Also added a note about the PYTHONPATH
+	environment variable.
+
+	* Extensions/wms/test/test_ogclib.py: The format specification is
+	a mime-type, not a graphic format, hence image/jpeg wou ld be the
+	proper format and not JPEG.  We'll also have to take care of the
+	encoding of / as %2F.
+
+2004-03-16  Martin Schulze  <joey at infodrom.org>
+
+	* Extensions/wms/test/test_ogclib.py: Added a (hopefully)
+	comprehensive test for the getMapURL method, built compare URLs
+	according to the documentation in OGC 01-068r3
+
+	* Extensions/wms/capabilities.py (WMSCapabilities): Added the
+	class WMSCapabilities to manage capabilites, will incorporate
+	parsing the capabilities response and provide details for other
+	classes.
+
+2004-03-12  Bernhard Herzog  <bh at intevation.de>
+
+	Support views in addition to normal tables in the postgis
+	shapestore
+
+	* Thuban/Model/postgisdb.py
+	(PostGISShapeStore._fetch_table_information): Add a fallback for
+	the case where the table name is not in the geometry_columns
+	table.  This is usually the case for views.  Also, set
+	self.shapestore here.
+	(PostGISShapeStore.ShapeType): No need to query the database all
+	the time.  The shape type is now determined in
+	_fetch_table_information
+
+	* test/postgissupport.py (PostgreSQLServer.new_postgis_db)
+	(PostgreSQLServer.get_static_data_db, PostGISDatabase.__init__):
+	New parameter to specify views.
+	(PostGISDatabase.has_data): Also compare the views.  New views
+	parameter
+	(PostGISDatabase.initdb): Create the views.
+	(PostgreSQLServer.get_default_static_data_db): Add the v_landmarks
+	view
+
+	* test/test_postgis_db.py
+	(TestPostGISShapestorePointFromViews): New.  Test a
+	PostGISShapeStore with a view
+	(TestPostGISShapestorePointOIDAsGIDColumn.setUp): Pass the name of
+	the geometry_column explicitly to test whether that works
+
+2004-03-12  Bernhard Herzog  <bh at intevation.de>
+
+	Final step for explicit id/geometry columns: Loading and saving
+
+	* Resources/XML/thuban-1.1.dtd: New.  Derived from thuban-1.0.dtd
+	with the following changes:
+	(dbshapesource): Two new attributes id_column and geometry_column
+
+	* Thuban/Model/save.py (SessionSaver.write): Use the new dtd
+	(SessionSaver.write_session): Use the new namespace
+	(SessionSaver.write_data_containers): Write the new dbshapesource
+	parameters
+
+	* Thuban/Model/load.py (SessionLoader.__init__): New namespace for
+	the new file format version
+	(SessionLoader.start_dbshapesource): Handle the new db parameters
+
+	* test/test_save.py: Update to the new dtd and namespace
+	(SaveSessionTest.test_save_postgis): Update the NonConnectionStore
+	mock object to provide a working IDColumn method.
+
+	* test/test_load_1_0.py: New.  Copy of the test_load.py before
+	today's changes but with the round-trip tests removed.
+
+	* test/test_load_0_9.py: Update doc-string.
+
+	* test/test_load.py: Update all .thuban files to the new dtd and
+	namespace.
+	(TestPostGISLayer.file_contents): Add the new dbshapesource
+	paramters
+
+2004-03-11  Bernhard Herzog  <bh at intevation.de>
+
+	Next step for explicit id/geometry columns: User interaction
+
+	* Thuban/UI/dbdialog.py (ChooseDBTableDialog.__init__): Rework how
+	the dialog is constructed. Add combo boxes to select id and
+	geometry column.  Rename some instance variables.
+	(ChooseDBTableDialog.GetTable): Return id and geometry column
+	names
+	(ChooseDBTableDialog.OnTableSelect): New. Event handler for
+	selections in the table list
+
+	* Thuban/UI/mainwindow.py (MainWindow.AddDBLayer): Use id_column
+	and geometry_column
+
+	* Thuban/Model/session.py (Session.OpenDBShapeStore): Add the new
+	parameters for id_column and geometry column of PostGISShapeStore
+	here as well.
+
+	* Thuban/Model/postgisdb.py (type_map): Add ROWID psycog type.
+	(_raw_type_map): New. Map raw PostgreSQL type ints to thuban types
+	(PostGISConnection.GeometryTables): Use a better query to
+	determine which relations in the database might be usable for
+	shapestores.  Now supports views as well but is more PostgreSQL
+	specific
+	(PostGISConnection.table_columns): New. Somewhat experimental
+	method to let the db dialogs provide lists of columns to users so
+	that they can select id and geometry columns.
+	(PostGISTable.__init__): The default value of the id_column
+	parameter is now None it still means "gid" effectively, though.
+	(PostGISTable.IDColumn): New introspection method to return a
+	column object for the id column
+	(PostGISShapeStore.GeometryColumn): New introspection method to
+	return a column object for the geometry column
+
+	* test/test_postgis_db.py
+	(TestPostGISConnection.test_gis_tables_non_empty):
+	Removed. Subsumed by the new:
+	(TestPostGISConnection.test_gis_tables_with_views_and_tables):
+	New. Tes the GeometryTables and table_columns methods with actual
+	tables and views.
+	(PointTests.test_id_column, PointTests.test_geometry_column):
+	New. tests for the new methods.
+	(TestPostGISShapestorePoint.setUp)
+	(TestPostGISShapestorePointSRID.setUp)
+	(TestPostGISShapestorePointExplicitGIDColumn.setUp): Fill the
+	instance variables needed by the new tests
+
+2004-03-11  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/classgen.py (GenQuantilesPanel.GetList): The row
+	numbers given to ReadValue are ordinals.
+
+2004-03-11  Bernhard Herzog  <bh at intevation.de>
+
+	Elimiate the requirement for PostGIS tables to have a column
+	called "gid".
+
+	* Thuban/Model/postgisdb.py (PostGISTable.__init__): New parameter
+	id_column to specify which column to use to identify rows.  Also
+	new instance variables id_column and quoted_id_column
+	(PostGISTable.RowIdToOrdinal, PostGISTable.RowOrdinalToId)
+	(PostGISTable.ReadRowAsDict, PostGISTable.ReadValue)
+	(PostGISTable.SimpleQuery): Use the id column name provided to the
+	constructor instead of "gid"
+	(PostGISShapeStore.__init__): New parameter id_column analogously
+	to PostGISTable.__init__.  This parameter is simply passed through
+	to the base class constructor
+	(PostGISShapeStore._create_col_from_description): Fix typo in
+	doc-string
+	(PostGISShapeStore.Shape, PostGISShapeStore.AllShapes)
+	(PostGISShapeStore.ShapesInRegion): Use the id column name
+	provided to the constructor instead of "gid"
+
+	* test/postgissupport.py
+	(PostgreSQLServer.get_default_static_data_db): New static table
+	landmarks_point_id with an id column != "gid.  Update the comments
+	a bit.
+	(skip_if_addgeometrycolumn_does_not_use_quote_ident): Fix typo in
+	doc-
+	(upload_shapefile): New parameter gid_column to use a name other
+	than "gid" for the column to store the shape ids
+
+	* test/test_postgis_db.py (TableTests): New.  Mixin-class
+	containing all tests previously in TestPostGISTable.  The actual
+	tests are the same but the code is a bit more configurable to
+	allow for different id columns etc.
+	(TestPostGISTable): Derive from TableTests now for the actual
+	tests.
+	(TestPostGISTableExplicitGIDColumn): New. Like TestPostGISTable
+	except that it the landmarks_point_id table to test the id_column
+	parameter
+	(PointTests): Extend the doc-string
+	(TestPostGISShapestorePointExplicitGIDColumn)
+	(TestPostGISShapestorePointOIDAsGIDColumn): New classes derived
+	from PointTests to test the explicit id_column parameter.  One
+	tests with the name of the column holding the shape ids, the other
+	uses PostgreSQL's OID column.  For the latter a number of methods
+	have to be overwritten to make them independent of the actual id
+	values.
+
+2004-03-08  Silke Reimer  <silke at intevation.de>
+
+	Update debian directory:
+
+	* debian/changelog: Added new version.
+	* deiban/rules: Updated management of patches (with cbds)
+	* debian/control: Added cbds to dependencies
+	* debian/patches/*: New. Adds better support for patches of thuban in
+	 		debian
+	* debian/menu: Syntax of menu changed slightly
+	* debian/setup.py.patch: removed because it has been moved to
+	  		debian/patechs/setup.py.patch
+	
+
+2004-02-26  Bernhard Herzog  <bh at intevation.de>
+
+	Create the Doc/technotes directory for text files with information
+	for developers
+
+	* Doc/technotes/README: New. README for the technotes
+
+	* Doc/technotes/coding_guidelines.txt: New. Coding guidelines for
+	Thuban
+
+	* Doc/technotes/release_process.txt: New. Used to be
+	HOWTO-Release.  Now slightly adapted to technote formatting style.
+
+	* HOWTO-Release: Removed.  It's contents are now in
+	Doc/technotes/release_process.txt
+
+2004-02-25  Bernhard Herzog  <bh at intevation.de>
+
+	* libraries/thuban/wxproj.cpp (get_wx_version): New.  Return the
+	version of wxWindows the module was compiled with so we can check
+	that against the wxPython version.
+
+	* Thuban/version.py (thuban_branch, thuban_release): New variables
+	controlling which and how Thuban versions are shown.  See the
+	comments for details.
+	(verify_versions): Also check that the wx version that wxproj is
+	compiled against matches that of the wxPython we use at runtime
+
+2004-02-20  Bernhard Herzog  <bh at intevation.de>
+
+	* Extensions/wms/wms.py (epsg_code_to_projection): Use
+	get_system_proj_file to read the epsg projections.  The old way
+	depended on the current directory being the top Thuban directory.
+
+2004-02-20  Bernhard Herzog  <bh at intevation.de>
+
+	* Extensions/svgexport/test/test_svgmapwriter.py
+	(TestVirtualDC.test_clippath): Remove a debug print
+
+2004-02-20  Bernhard Herzog  <bh at intevation.de>
+
+	* Extensions/svgexport/__init__.py: New.  Turn
+	Extensions/svgexport into a package.
+
+	* Extensions/svgexport/svgmapwriter.py: Reorder the imports and
+	doc-string a bit.  The doc-string must come first, otherwise it's
+	not a doc-string.  The __future__ import must be the first thing
+	after the doc-string.  Use only double quotes in doc-strings.
+	Single quotes trip up emacs syntax highlighting if the text
+	contains apostrophes.
+
+2004-02-20  Bernhard Herzog  <bh at intevation.de>
+
+	* Extensions/svgexport/test/__init__.py,
+	Extensions/svgexport/test/test_svgmapwriter.py: New. Initial test
+	suite for svgexport
+
+	* test/runtests.py (find_test_modules): New. Function with the
+	module finding code from main.
+	(main): Use find_test_modules to figure out the default test
+	modules and take modules from Extensions.svgexport.test too.
+
+2004-02-19  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/application.py (ThubanApplication.OnInit): Make sure
+	the mainwindow has a reference to the map of the initial session.
+	This fixes a bug introduced with the fix for RT#2245
+
+2004-02-19  Bernhard Herzog  <bh at intevation.de>
+
+	* Extensions/svgexport/svgsaver.py,
+	Extensions/svgexport/svgmapwriter.py,
+	Extensions/svgexport/maplegend.py: Added again.  This time in the
+	correct place.
+
+2004-02-17  Bernhard Herzog  <bh at intevation.de>
+
+	Fix for RT#2245
+
+	* Thuban/UI/application.py (ThubanApplication.OnInit): Initialize
+	instance variables before trying to create any windows.  Creating
+	windows can start an event loop if e.g. message boxes are popped
+	up for some reason, and event handlers, especially EVT_UPDATE_UI
+	may want to access things from the application.
+	(ThubanApplication.maps_changed): The mainwindow may not have been
+	created yet, so check whether it has been created before calling
+	its methods
+
+	* Thuban/UI/view.py (MapCanvas.OnIdle): Only try to redraw if we
+	have a map
+
+2004-02-17  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_svgmapwriter.py, Extensions/svgsaver.py,
+	Extensions/svgmapwriter.py, Extensions/maplegend.py,
+	extensions/svgexport/svgsaver.py,
+	extensions/svgexport/svgmapwriter.py,
+	extensions/svgexport/maplegend.py: Removed.  These files were in
+	the wrong places or didn't work at all.
+
+2004-02-16  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py (MapCanvas.Export): Remove accidentally added
+	line
+
+2004-02-16  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py (MapCanvas.Export): Avoid UnboundLocalError.
+
+2004-02-15  Markus Rechtien  <markus at intevation.de>
+	
+	* Extensions/svgexport/svgmapwriter.py: New. Adds the capability
+	to write a session to a file in SVG format.
+	* Extensions/svgexport/svgsaver.py: New. Uses svgmapwriter.py
+	to write a SVG map of a session.
+	* Extensions/svgexport/maplegend: New. Writes a basic maplegend
+	in SVG format for the current session.
+
+2004-02-13  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.AddDBLayer): When the layer
+	can't be created, return immediately after displaying the error
+	message.
+
+2004-02-11  Bernhard Herzog  <bh at intevation.de>
+
+	Handle postgis tables with more than one geometry column.
+
+	* Thuban/Model/postgisdb.py
+	(PostGISTable._fetch_table_information): Delegate the creation of
+	column objects to a different method so that we can extend that in
+	derived classes
+	(PostGISTable._create_col_from_description): New. Column object
+	creation part of _fetch_table_information
+	(PostGISShapeStore._create_col_from_description): New. Extend
+	inherited method to handle geometry columns
+	(PostGISShapeStore.__init__): New parameter geometry_column to
+	specify which geometry column to use.  Optional but mandatory for
+	tables with more than one geometry column
+	(PostGISShapeStore._fetch_table_information): Also use the name of
+	the geometry column when looking for the srid
+	(PostGISShapeStore.ShapeType): Also use the name of the geometry
+	column when looking for the shape type
+
+	* test/test_save.py (SaveSessionTest.test_save_postgis): Adapt
+	NonConnectionStore to changes in the PostGISShapeStore
+
+	* test/test_postgis_db.py
+	(TestPostGISSpecialCases.test_shapestore_two_geom_cols): Test
+	PostGISShapeStore with tables having two geometry columns.
+
+2004-02-10  Bernhard Herzog  <bh at intevation.de>
+
+	Fix some postgis problems.  What remains to be done is real
+	handling of SRIDs as they affect how reprojection is done
+
+	* Thuban/Model/postgisdb.py (quote_identifier): Fix typo in
+	doc-string
+	(PostGISShapeStore._fetch_table_information): New. Extend
+	inherited method to retrieve srid
+	(PostGISShapeStore.BoundingBox): Handle tables without data.
+	extent yields NULL for those
+	(PostGISShapeStore.ShapesInRegion): Use the srid of the table.
+
+	* test/test_postgis_db.py
+	(TestPostGISSpecialCases.test_shapestore_empty_table): New test
+	for the special case of a table without any data
+	(TestPostGISShapestorePointSRID): New class with tests for a table
+	that uses srids
+	(PolygonTests): Fix a doc-string typo
+
+	* test/postgissupport.py (PostGISDatabase.__init__): New parameter
+	reference_systems with a specification of spacial reference
+	systems to create in the new db.
+	(PostgreSQLServer.new_postgis_db)
+	(PostgreSQLServer.get_static_data_db): New parameter
+	reference_systems to be passed through ultimately to
+	PostGISDatabase.  In new_postgis_db also check whether an existing
+	db already has the right srids
+	(PostgreSQLServer.get_default_static_data_db): Add srids and a
+	table that uses srids
+	(PostGISDatabase.initdb): Create the entries for the reference
+	systems
+	(PostGISDatabase.has_data): Add reference_systems parameter to
+	check for those too
+	(upload_shapefile): New parameter srid to create tables with a
+	specific srid
+
+2004-02-06  Frank Koormann  <frank at intevation.de>
+
+	* po/pt_BR.po: Fixed charset
+
+2004-02-05  Frank Koormann  <frank at intevation.de>
+
+	* po/pt_BR.po: Fixed format string for error message, missing %s
+	added (Thuban/UI/application.py:273)
+
+2004-02-03  Frank Koormann  <frank at intevation.de>
+	
+	First version of Portuguese (Brazilian) translation
+
+	* po/pt_BR.po: New, translation of pot (2004-01-15 16:07+0300) for
+	Brazilian Portuguese by Eduardo Patto Kanegae.
+
+	* Thuban/UI/about.py (About.__init.py__): Added Eduardo to the list of
+	translators.
+
+
+2004-01-22  Frank Koormann  <frank at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Added section on installation of
+	Thuban under Win32 systems. Fixed image path references in the postgis
+        section. Some minor source formattings.
+
+2004-01-21  Frank Koormann  <frank at intevation.de>
+
+	Make Thuban remember path selections (at least for one application run).
+
+	* Thuban/UI/application.py (Application.OnInit): Initialize path as a 
+	attribute of application object. Path is a dictionary of
+	strings, currently with the items "data" and "projection".  
+	(Application.SetPath): New, stores path for the specified item.
+	(Application.Path): New, return path for the specified item.
+
+	* Thuban/UI/mainwindow.py 
+	(MainWindow.OpenSession, MainWindow.SaveSessionAs, 
+	MainWindow.AddLayer, MainWindow.AddRasterLayer,
+	MainWindow.TableOpen): Access "data" path information of the
+	application.
+	
+	* Thuban/UI/projdialog.py (ProjFrame._OnImport, ProjFrame._OnExport):
+	Access "projection" path information of the application.
+
+2004-01-05  Bernhard Herzog  <bh at intevation.de>
+
+	* po/ru.po: Updated translations from Alex Shevlakov
+
+2004-01-05  Bernhard Herzog  <bh at intevation.de>
+
+	* po/Makefile, po/README: Move the description of how to generate
+	the translation statistics to the README.
+
+2003-12-23  Bernhard Herzog  <bh at intevation.de>
+
+	* NEWS: Update for 1.0.0
+
+	* po/it.po: Another update from Maurizio Napolitano
+
+2003-12-23  Bernhard Herzog  <bh at intevation.de>
+
+	* po/it.po: Updated translation from Maurizio Napolitano
+
+2003-12-23  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/join.py (JoinDialog.__init__): Mark one more string
+	for translation
+
+	* Thuban/UI/mainwindow.py (MainWindow.TableRename)
+	(MainWindow.RenameMap, MainWindow.RenameLayer): Mark some more
+	strings for translation
+
+	* po/de.po: Update with the newly marked strings.
+
+2003-12-22  Bernhard Herzog  <bh at intevation.de>
+
+	* HOWTO-Release: Fix the places where version numbers have to be
+	updated
+
+2003-12-22  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (setup call): 1.0.0, yeah!
+
+	* Thuban/version.py (longversion): 1.0.0, yeah!
+
+	* Thuban/Model/load.py (SessionLoader.__init__): Accept the
+	1.0.0 namespace too
+
+	* Thuban/Model/save.py (SessionSaver.write_session): Save with
+	1.0.0 namespace
+
+	* test/test_load.py (LoadSessionTest.dtd)
+	(TestSingleLayer.file_contents)
+	(TestNonAsciiColumnName.file_contents)
+	(TestLayerVisibility.file_contents)
+	(TestClassification.file_contents, TestLabels.file_contents)
+	(TestLayerProjection.file_contents)
+	(TestRasterLayer.file_contents, TestJoinedTable.file_contents)
+	(TestLabelLayer.file_contents, TestPostGISLayer.file_contents)
+	(TestPostGISLayerPassword.file_contents)
+	(TestLoadError.file_contents, TestLoadError.test): Update for
+	1.0.0 namespace
+
+	* test/test_save.py (SaveSessionTest.dtd)
+	(SaveSessionTest.testEmptySession)
+	(SaveSessionTest.testSingleLayer)
+	(SaveSessionTest.testLayerProjection)
+	(SaveSessionTest.testRasterLayer)
+	(SaveSessionTest.testClassifiedLayer)
+	(SaveSessionTest.test_dbf_table)
+	(SaveSessionTest.test_joined_table)
+	(SaveSessionTest.test_save_postgis): Update for 1.0.0 namespace
+
+2003-12-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/load.py (SessionLoader.start_label): Make sure the
+	alignment flags are byte strings not unicode and that they have
+	valid values
+
+	* test/test_load.py (TestLabelLayer): New. Test loading (and
+	indirectly saving) of maps with labels.
+
+2003-12-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/tableview.py (TableGrid.OnDestroy)
+	(TableGrid.__init__): Handle EVT_WINDOW_DESTROY in the grid to
+	unsubscribe all subscribers.
+	(LayerTableFrame.OnDestroy): Do not unsubscribe any messages from
+	self.grid since it may already have been destroyed.
+	Fixes RT #2256
+
+2003-12-19  Bernhard Herzog  <bh at intevation.de>
+
+	* po/fr.po, po/es.po: Updated translations from Daniel Calvelo
+
+2003-12-16  Bernhard Herzog  <bh at intevation.de>
+	
+	* debian/bitmappath.patch, debian/setup.py.patch:
+		added to ensure compliance with FHS for debian
+	* debian/rules, debian/changelog:
+	    added patches in rules to ensure compliance with FHS for debian
+
+2003-12-16  Bernhard Herzog  <bh at intevation.de>
+
+	* po/Makefile (mo): Make the output a bit nicer so that it prints
+	statistics about the translations. Add a comment how produce even
+	nicer statistics with sed.
+
+2003-12-09  Frank Koormann   <frank at intevation.de>
+
+	* Resources/Projections/defaults.proj:
+	French projection sample with correct accents (UNICODE).
+
+2003-12-05  Bernhard Herzog  <bh at intevation.de>
+
+	* MANIFEST.in: Add the devtools directory
+
+	* setup.py (setup call): Use license instead of licence. This
+	silences a deprecation warning on Python 2.3
+
+2003-12-05  Frank Koormann   <frank at intevation.de>
+
+	Documentation synced with 1.0rc1
+
+	* Doc/manual/thuban-manual.xml: 
+	Minor formatting changes and references to database layers .
+	Introduction.Internationalization: New section on i18n.
+	MapManagement.AddingandRemovingLayers: Added item on database layers.	
+	MapManagement.TheLegend: Added section and screenshot on popup menu.
+	ProjectionManagement: Updated screenshot and sentence on EPSG.
+	Appendix.SupportedDataSources: Added PostGIS.
+	Appendix.WorkingwithPostGIS: New section.
+
+	* Doc/manual/images/6_projection.png: Updated screenshot including 
+	EPSG checkboxes.
+
+	* Doc/manual/images/3_5_popup_menu.png: New, popup menu screenshot.
+
+	* Doc/manual/images/app_postgis_add_layer.png,
+	Doc/manual/images/app_postgis_db_add.png, 
+	Doc/manual/images/app_postgis_db_management.png:
+	New screenshots focussing on database layers
+
+2003-12-05  Frank Koormann   <frank at intevation.de>
+
+	* Thuban/UI/projdialog.py (load_user_proj): If user.proj is missing
+	write warning to stderr instead of rising a warning dialog
+
+2003-12-03  Bernhard Herzog  <bh at intevation.de>
+
+	Fix for RT #2243
+
+	* Thuban/UI/mainwindow.py (MainWindow.has_selected_shape_layer):
+	New. Like has_selected_layer but for shape layers only
+	(_has_selected_shape_layer): New. Like _has_selected_layer but for
+	shape layers only
+	(layer_show_table command, layer_jointable command): Use these
+	commands should only be available for shape layers
+
+2003-12-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.Unsubscribe): Deal with
+	publishers that are wx objects and may have been destroyed by wx
+	already. Fixes RT #2242.
+
+2003-12-03  Bernhard Herzog  <bh at intevation.de>
+
+	* po/ru.po: Updates from Alex Shevlakov
+
+2003-12-03  Silke Reimer <silkeintevation.de>
+
+	* debian/control, debian/changelog: Added gdal-support to
+		debian package, updated to new thuban version
+
+
+2003-12-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Lib/version.py: New. Module for version number
+	manipulations. The version of make_tuple here also deals better
+	with more unusual version number strings, such as e.g.
+	"1.2+cvs20031111"
+
+	* Thuban/version.py (make_tuple): Removed. It's now in
+	Thuban.Lib.version. Use that implementation instead.
+
+	* test/test_lib_version.py: New. Tests for Thuban/Lib/version.py
+
+2003-12-02  Bernhard Herzog  <bh at intevation.de>
+
+	* MANIFEST.in: Add debian files
+
+	* setup.py (setup call): Add packages for the Extensions so that
+	they're installed too
+	(data_files): Add READMEs and sample data from some Extensions
+
+	* NEWS: Add note about the extensions in binary packages
+
+2003-12-02  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/save.py (SessionSaver.write_session): Save files
+	with the thuban-1.0rc1
+
+	* Thuban/Model/load.py (SessionLoader.__init__): Recognize the
+	thuban-1.0rc1 namespace too
+
+	* test/test_save.py (SaveSessionTest.dtd)
+	(SaveSessionTest.testEmptySession)
+	(SaveSessionTest.testSingleLayer)
+	(SaveSessionTest.testLayerProjection)
+	(SaveSessionTest.testRasterLayer)
+	(SaveSessionTest.testClassifiedLayer)
+	(SaveSessionTest.test_dbf_table)
+	(SaveSessionTest.test_joined_table)
+	(SaveSessionTest.test_save_postgis): Update to thuban-1.0rc1
+	namespace
+
+	* test/test_load.py (LoadSessionTest.dtd): Update to thuban-1.0rc1
+	namespace
+	(TestSingleLayer.file_contents)
+	(TestNonAsciiColumnName.file_contents)
+	(TestLayerVisibility.file_contents)
+	(TestClassification.file_contents, TestLabels.file_contents)
+	(TestLayerProjection.file_contents)
+	(TestRasterLayer.file_contents, TestJoinedTable.file_contents)
+	(TestPostGISLayer.file_contents)
+	(TestPostGISLayerPassword.file_contents)
+	(TestLoadError.file_contents, TestLoadError.test): Update to
+	thuban-1.0rc1 namespace
+
+2003-12-01  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (proj4_prefix, wx_prefix, gdal_prefix): Fix these for
+	nt to better match Intevation's current w32 setup
+
+	* HOWTO-Release: Add note about updating MANIFEST.in
+
+	* MANIFEST.in: Add the Extensions
+
+	* NEWS: Update for 1.0rc1
+
+2003-12-01  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.AddLayer): Change the wild
+	cards for the dialog so that shapefiles ending in all uppercase
+	SHP are listed too
+
+2003-11-28  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/version.py (longversion): Update to 1.0rc1
+
+	* setup.py (setup call): Update version to 1.0rc1. Use the
+	thuban at intevation.de email address as author email instead of my
+	personal one.
+
+2003-11-28  Bernhard Herzog  <bh at intevation.de>
+
+	* po/de.po: Update german translation.
+
+2003-11-28  Bernhard Herzog  <bh at intevation.de>
+
+	Unify the filenames stored in .thuban files so that the .thuban
+	files are more platform independend
+
+	* Thuban/Model/save.py (unify_filename): New. Unify filenames so
+	that they can be used on both windows and unix
+	(SessionSaver.prepare_filename): New. Handle all filename
+	transformations for filenames stored in the thuban file
+	(SessionSaver.write_data_containers, SessionSaver.write_layer):
+	Use prepare_filename
+
+	* test/test_save.py (SaveSessionTest.testSingleLayer)
+	(SaveSessionTest.testLayerProjection)
+	(SaveSessionTest.testRasterLayer)
+	(SaveSessionTest.testClassifiedLayer)
+	(SaveSessionTest.test_dbf_table)
+	(SaveSessionTest.test_joined_table): Filenames are always stored
+	with slashes on all currently supported platforms so adapt all
+	tests to this
+
+	* test/test_load.py (LoadSessionTest.filenames): With the new
+	filename scheme the filenames in the tests should be
+	understandable on all currently supported platforms so we turn
+	this into an empty list because we don't have to normalize them
+	anymore
+
+2003-11-28  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_layer.py (TestLayer.test_arc_layer_with_projection):
+	Add the ellipsoid to the projection since some Proj versions
+	complain if it's missing.
+
+2003-11-27  Bernhard Herzog  <bh at intevation.de>
+
+	Corect some bounding box projection problems
+
+	* Thuban/Model/proj.py (Projection.InverseBBox): New. Inverse
+	version of ForwardBBox
+	(Projection._transform_bbox): New. common implementation of
+	ForwardBBox and InverseBBox
+	(Projection.ForwardBBox): Use _transform_bbox.
+
+	* test/test_proj.py (TestProjection.test): Add test for
+	InverseBBox
+
+	* Thuban/Model/layer.py (Layer.LatLongBoundingBox)
+	(Layer.ShapesBoundingBox, RasterLayer.LatLongBoundingBox): Use the
+	new InverseBBox method to determine the unprojected bounding box
+	(Layer.ShapesInRegion): Use the ForwardBBox method to project the
+	bbox.
+
+	* test/test_layer.py (TestLayer.test_point_layer_with_projection):
+	Removed.
+	(TestLayer.test_arc_layer_with_projection): New. This test is
+	better able to test whether bounding boxes are projected correctly
+	than test_point_layer_with_projection
+
+	* Thuban/UI/viewport.py (ViewPort.map_projection_changed): Use
+	InverseBBox to unproject bboxes
+
+2003-11-25  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/about.py (About.__init__): Make sure we have ASCII
+	source code.
+
+2003-11-25  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.__getattr__): Removed. It was only
+	there for backwards compatibility and all code relying on that
+	should have been updated by now.
+
+2003-11-25  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_load.py (TestClassification.test): Add the missing
+	round trip test.
+	(TestClassification.file_contents): Update to the newest file
+	format
+
+2003-11-25  Bernhard Herzog  <bh at intevation.de>
+
+	Add very experimental (and possibly dangerous) extension to draw
+	polygons:
+
+	* Extensions/drawshape/README: New. Brief installation
+	instructions
+
+	* Extensions/drawshape/drawshape.py: New. Implementation of the
+	drawshape extensions
+
+	* Extensions/drawshape/patch.diff: Patch to apply before the
+	extension can be used.
+
+2003-11-24  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/data.py (ShapefileStore._open_shapefile)
+	(ShapefileStore.__init__): Factor opening the shapefile into a
+	separate method (the new _open_shapefile). This makes the code a
+	bit more readable but the real reason is that it makes some evil
+	hacks easier. :-)
+
+2003-11-24  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/load.py (SessionLoader.check_attrs): If no
+	converter is specified for an attribute assume it's a string
+	containing only Latin1 characters. Update doc-string accordingly.
+	This change should fix many places where unicode objects might
+	accidentally enter Thuban.
+
+	* test/test_load.py (TestNonAsciiColumnName): New test to check
+	what happens with column names in DBF files that contain non-ascii
+	characters
+
+2003-11-21  Bernhard Herzog  <bh at intevation.de>
+
+	Enable the experimental attribute editing again and introduce a
+	command line switch to actually activate it
+
+	* Thuban/UI/main.py (options): New. Container for options set on
+	the commmand line
+	(main): Add the --enable-attribute-editing flag.
+
+	* Thuban/UI/identifyview.py (IdentifyView.__init__): If attribute
+	editing is enabled use the grid ctrl which allows editing of the
+	values
+
+	* Thuban/Model/transientdb.py (AutoTransientTable.write_record):
+	New. Just delegate this to the underlying table.
+
+2003-11-20  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_proj.py (ProjFileReadTests.test_read_unreadable_file):
+	Skip this test if run under non-posix systems since it only works
+	there
+
+2003-11-19  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/resource.py: Rework the way gdal support is
+	determined so that we can give a reason in the about why gdal is
+	not supported.
+	(gdal_support_status): New. Variable holding a string with the
+	reason for no gdal support
+
+	* Thuban/UI/about.py (About.__init__): Add the reason why gdal is
+	not supported to the message
+
+2003-11-19  Bernhard Herzog  <bh at intevation.de>
+
+	Remove the old table interface and its test cases
+
+	* Thuban/Model/table.py (OldTableInterfaceMixin): Removed.
+	(DBFTable, MemoryTable): Do not derive from OldTableInterfaceMixin
+	anymore
+
+	* Thuban/Model/transientdb.py (TransientTableBase)
+	(AutoTransientTable): Do not derive from OldTableInterfaceMixin
+	anymore
+
+	* test/test_table.py: Removed since the old interface it tests is
+	gone.
+
+	* test/runtests.py (main): The old table interface is gone and
+	with it the deprecation warnings so remove the code that turns
+	these warnings into errors
+
+2003-11-19  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_table.py: Revert to revision 1.5 again. Changing the
+	tests to use the new table interface is completely wrong since the
+	whole purpose of the tests in this module is to test the old
+	interface.
+
+2003-11-18  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/postgisdb.py (PostGISConnection.MatchesParameters):
+	New. Test whether the connection matches a set of connection
+	parameters
+
+	* Thuban/UI/dbdialog.py (DBFrame.conns_changed): Fix doc-string
+	(DBFrame.OnAdd): Use the new MatchesParameters method when looking
+	for existing connections with the same parameters and break out of
+	the loop correctly.
+
+	* test/test_postgis_db.py (TestBriefDescription)
+	(TestPostGISSimple.test_brief_description): Rename
+	TestBriefDescription to TestPostGISSimple and the test method to
+	test_brief_description so that we can add more test methods.
+	(TestPostGISSimple.test_matches_parameters): New. Test the new
+	MatchesParameters method
+
+2003-11-18  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Lib/connector.py (Publisher): Introduce a new flag,
+	_was_destroyed, to indicate whether an publisher instance has
+	already been destroyed.
+	(Publisher.Unsubscribe): Only disconnect if the publisher has not
+	been destroyed yet.
+	(Publisher.Destroy): Set the _was_destroyed flag to true.
+
+	* test/test_connector.py
+	(TestPublisher.test_unsubscribe_after_destroy): New. Test that
+	calling Unsubscribe after Destroy doesn't raise an exception
+
+2003-11-14  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/identifyview.py (IdentifyView.selected_shape): Fix
+	typo in doc-string
+
+2003-11-13  Bernhard Herzog  <bh at intevation.de>
+
+	Quote table and column names properly for postgis.
+
+	* Thuban/Model/postgisdb.py (quote_identifier): New. Function to
+	quote an identifier for use in an sql statement
+	(PostGISColumn.__init__): Add the quoted_name attribute
+	(PostGISTable.__init__): New instance variable quoted_tablename
+	(PostGISTable._fetch_table_information): Use the quoted table
+	name. New isntance variable quoted_geo_col with a quoted version
+	of geometry_column
+	(PostGISTable.NumRows, PostGISTable.RowIdToOrdinal)
+	(PostGISTable.RowOrdinalToId): Use the quoted table name
+	(PostGISTable.ReadValue, PostGISTable.ValueRange)
+	(PostGISTable.UniqueValues, PostGISTable.SimpleQuery)
+	(PostGISShapeStore.BoundingBox, PostGISShapeStore.Shape)
+	(PostGISShapeStore.AllShapes, PostGISShapeStore.ShapesInRegion):
+	Use quoted table and column names
+
+	* test/test_postgis_db.py (TestPostGISSpecialCases)
+	(TestPostGISIgnoredColumns): Rename the class to
+	TestPostGISSpecialCases because that better describes the new
+	cases
+	(TestPostGISSpecialCases.test_unsupported_types)
+	(TestPostGISSpecialCases.test): Rename the method to
+	test_unsupported_types because we need a more descriptive name now
+	that there are more methods
+	(TestPostGISSpecialCases.test_table_name_quoting)
+	(TestPostGISSpecialCases.test_column_name_quoting)
+	(TestPostGISSpecialCases.test_shapestore_name_quoting): New test
+	cases to test quoting of table and column names in PostGISTable
+	and PostGISShapeStore
+
+	* test/postgissupport.py
+	(skip_if_addgeometrycolumn_does_not_use_quote_ident): New. Skip if
+	AddGeometryColumn desn't support table or column names with sapces
+	or double quotes
+
+2003-11-12  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Extensions/wms/__init__.py: New: Init to make this
+	directory a package.
+
+	* Extensions/wms/wms.py: New: Provide layers via OGC WMS.
+
+2003-11-11  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/resource.py (EPSG_DEPRECATED_PROJ_FILE): New.
+	Constant for the file woth deprecated epsg projections
+	(get_system_proj_file): Update doc-string
+
+	* Thuban/UI/projdialog.py (ProjFrame.build_dialog): Add a space
+	above the EPS widgets, introduce a check box for the deprecated
+	eps projections and a label for the epsg widgets
+	(ProjFrame._OnShowEPSG): Handle the deprecated EPSG projections
+	too
+
+2003-11-11  Bernhard Herzog  <bh at intevation.de>
+
+	Avoid warnings when run under Python 2.3
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.draw_point_shape)
+	(BaseRenderer.draw_label_layer): Coordinates must be ints.
+
+	* Thuban/UI/renderer.py (MapRenderer.make_point): Turn this into a
+	real method so that we can convert to int.
+	(MapRenderer.label_font): The font size mist be an int.
+
+	* Thuban/UI/common.py (Color2wxColour): The color values must be
+	ints. Also, remove the unnecessary asserts.
+
+	* test/test_load_0_8.py (TestUnicodeStrings.file_contents)
+	(TestUnicodeStrings.test): Python source code should not contain
+	non-ascii characters unless an encoding is specified in the file.
+	Therefore use \x escapes in the string literals for non-ascii
+	characters.
+
+2003-11-11  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/resource.py (get_system_proj_file): Add a filename
+	parameter so that this function can be used for all proj files in
+	Resource/Projections
+	(DEFAULT_PROJ_FILE, EPSG_PROJ_FILE): New. Predefined filenames for
+	get_system_proj_file
+
+	* Thuban/UI/projdialog.py (ProjFrame.__init__): Instead of one
+	ProjFile self.__sysProjFile use a dictionary of system ProjFile
+	objects self._sys_proj_files
+	(ProjFrame.build_dialog): Adapt to the new changes in the
+	ProjectionList constructor. Add a check button to toggle whether
+	EPSG projections are shown
+	(ProjFrame._OnShowEPSG): New. Handler for the epsg check button
+	events.
+	(ProjFrame.load_user_proj, ProjFrame.load_system_proj): Only show
+	the busy cursor if the files have not yet been loaded by the
+	dialog.
+	(ProjFrame.load_system_proj): Add a parameter for the name of the
+	proj file. Maintain the dictionary of system projections
+	self._sys_proj_files
+
+	* Thuban/UI/projlist.py (ProjectionList): Merge the system_projs,
+	user_projs parameters into one parameter proj_files which is a
+	list of proj files.
+	(ProjectionList._subscribe_proj_files)
+	(ProjectionList._unsubscribe_proj_files): New. Move
+	subscription/unsubscription of projfile messages to separate
+	methods
+	(ProjectionList.Destroy): The unsubscribe is now done in
+	_unsubscribe_proj_files
+	(ProjectionList.update_projections): We now have a list of proj
+	file objects
+	(ProjectionList.SetProjFiles): New method to set a new list of
+	proj file objects
+
+	* test/test_proj.py (ProjFileReadTests.test_get_system_proj_file):
+	Specify explicitly which system proj file to load.
+
+2003-11-11  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/load.py (SessionLoader.Destroy): New. Clear all
+	instance variables to cut cyclic references. The GC would have
+	collected the loader eventually but it can happen that it doesn't
+	run at all until thuban is closed (2.3 but not 2.2 tries a bit
+	harder and forces a collection when the interpreter terminates)
+	(load_session): Call the handler's Destroy method to make sure
+	that it gets garbage collected early. Otherwise it will be
+	collected very late if at all and it holds some references to e.g.
+	shapestores and the session which can lead to leaks (of e.g. the
+	temporary files)
+
+	* test/test_load.py (TestSingleLayer.test_leak): New. test for the
+	resource leak in load_session
+
+2003-11-10  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/baserenderer.py: Add a way to specify how layers in
+	extensions are to be rendered.
+	(_renderer_extensions): New. List with renderer for layers in
+	extensions
+	(add_renderer_extension): New. Add a renderer extension
+	(init_renderer_extensions): New. Init the renderer extensions
+	(BaseRenderer.render_map_incrementally): Search
+	_renderer_extensions for how to draw unknown layer types
+	(BaseRenderer.draw_raster_data): Add format parameter so that
+	formats other than BMP can be drawn
+	(BaseRenderer.draw_raster_layer): Pass an explicit format to
+	draw_raster_data
+
+	* Thuban/UI/renderer.py (raster_format_map): New. Mapping form the
+	strings of the format parameter of draw_raster_data method to wx
+	constants
+	(MapRenderer.draw_raster_data): Add the format parameter and use
+	raster_format_map to map it to the right wxwindows constant for
+	wxImageFromStream
+
+	* test/test_baserenderer.py (SimpleRenderer.draw_raster_data): Add
+	the format parameter and record it
+	(TestBaseRenderer.test_raster_no_projection): check the format
+	paramter of the draw_raster_data method
+	(TestBaseRenderer.test_renderer_extension): New. Test the renderer
+	extension facility
+
+2003-11-07  Bernhard Herzog  <bh at intevation.de>
+
+	Tweak the usage of the sqlite database to make common use cases
+	more responsive. In most cases copying the data to the sqlite
+	database takes so long that using sqlite doesn't have enough
+	advantages.
+
+	* Thuban/Model/transientdb.py (TransientTableBase.ValueRange): Add
+	comments about performance and query the min and max in separate
+	statements because only that way will indexes be used.
+	(TransientTableBase.UniqueValues): Add some comments about
+	performance.
+	(AutoTransientTable.ValueRange, AutoTransientTable.UniqueValues):
+	Do not copy the data to the transient DB but use the transient
+	copy if it exists. See the new comments for the performance trade
+	offs
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_auto_transient_table): Make sure that the
+	data is copied to the transient database at some point.
+
+2003-11-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/data.py (ShapefileStore.ShapesInRegion): Bind some
+	globals to locals so that it's a bit faster
+
+2003-11-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/baserenderer.py
+	(BaseRenderer.draw_shape_layer_incrementally): Use the ReadValue
+	method. ReadValue is faster than ReadRowAsDict since it only reads
+	one cell especially now that the dbf file objects actually
+	implement it.
+
+	* Thuban/Model/table.py (DBFTable.ReadValue): Use the new
+	read_attribute method of the dbf objects
+
+2003-11-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Extensions/profiling/profiling.py (popup_dialog_box): New config
+	variable to indicate whether the result should be shown in a
+	dialog box
+	(profile_screen_renderer, time_screen_renderer): Only show a
+	dialog box if popup_dialog_box is true.
+	(profile_screen_renderer): Flush stdout after the printing the
+	first part of the "profiling..." message
+
+	* Thuban/UI/baserenderer.py
+	(BaseRenderer.draw_shape_layer_incrementally): Cache the pens and
+	brushes for the groups so that they're not created over and over
+	again
+
+	* Thuban/Model/classification.py (Classification.__getattr__)
+	(Classification._compile_classification)
+	(Classification._clear_compiled_classification): New. Methods to
+	manage a 'compiled' representation of the classification groups
+	which is created on demand
+	(Classification.InsertGroup, Classification.RemoveGroup)
+	(Classification.ReplaceGroup): reset the compiled representation
+	(Classification.FindGroup): Use the compiled representation to
+	find the matching group
+	(ClassGroupRange.GetRangeTuple): New. Return the range as a tuple
+
+2003-10-31  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/classification.py (Classification.SetDefaultGroup):
+	Send a CLASS_CHANGED message
+	(Classification.RemoveGroup): Send a CLASS_CHANGED message and do
+	not return the removed group since it wasn't used.
+
+	* test/test_classification.py
+	(TestClassification.test_set_default_group): New. Test the
+	SetDefaultGroup method
+	(TestClassification.test_insert_group): New. Test the InsertGroup
+	method
+	(TestClassification.test_remove_group): New. Test the RemoveGroup
+	method
+	(TestClassification.test_replace_group): New. Test the
+	ReplaceGroup method
+
+2003-10-31  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_classification.py (TestClassification.setUp):
+	Subscribe to the CLASS_CHANGED messages
+	(TestClassification.tearDown): New. Destroy the classification
+	properly
+	(TestClassification.test_defaults): Add tests for the default line
+	width and whether no messages were sent yet
+	(TestClassification.test_set_default_properties): Add tests for
+	messages and setting the default line width
+	(TestClassification.test_add_singleton)
+	(TestClassification.test_add_range)
+	(TestClassification.test_multiple_groups): Add tests for messages
+
+2003-10-31  Bernhard Herzog  <bh at intevation.de>
+
+	Some more refactoring in preparation for new tests:
+
+	* test/test_classification.py (TestClassification.setUp): New.
+	Instantiate the classification here. Update the test methods
+	accordingly.
+	(TestClassification.test_multiple_groups): Make sure that the two
+	singletons matching 1 are considered different.
+
+2003-10-31  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_classification.py (red, green, blue): New. These
+	constants were used in several cases. Update the relevant methods.
+	(TestClassification.test_defaults)
+	(TestClassification.test_set_default_properties)
+	(TestClassification.test_add_singleton)
+	(TestClassification.test_add_range)
+	(TestClassification.test_multiple_groups)
+	(TestClassification.test_deepcopy): New. These were formerly all
+	part of the single method test.
+	(TestClassification.test_deepcopy): Removed.
+	(TestClassIterator): Removed. The test case is now a method of
+	TestClassification since it tests part of the public interface of
+	Classification
+	(TestClassification.test_iterator): New. Used to be
+	TestClassIterator effectively
+
+2003-10-31  Jan-Oliver Wagner <jan at intevation.de>
+
+	GUIfied the functions of the profiling extension.
+
+	* /Extensions/profiling/__init__.py: New: Init to make this
+	directory a package.
+
+	* Extensions/profiling/profiling.py: Moved menu entries to
+	the Extensions menu. Applied _() for strings.
+	(profile_screen_renderer): Catch the detailed printout and present
+	it in a dialog.
+	(time_screen_renderer): Raise a dialog to present the result instead
+	of printing it to stdout.
+
+2003-10-31  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_classification.py (TestClassGroupProperties)
+	(TestClassGroup, TestClassGroupDefault, TestClassGroupRange)
+	(TestClassGroupSingleton, TestClassIterator, TestClassification):
+	Split TestClassification into several classes, one for each class
+	being tested. TestClassification itself now only tests
+	Classification. This split makes changes to the tests a bit easier
+
+2003-10-31  Bernhard Herzog  <bh at intevation.de>
+
+	* Extensions/profiling/profiling.py: New. Extension to measure
+	Thuban performance
+
+2003-10-31  Frank Koormann <frank at intevation.de>
+
+	Added two items to legend popup menu: Remove Layer and Show Layer Table
+
+	* Thuban/UI/legend.py (LegendPanel._OnRemoveLayer,
+	LegendPanel._OnShowTable): New event handlers, call the corresponding 
+	mainwindow methods.
+	(LegendTree._OnRightClick): Added items to popup menu.
+
+2003-10-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/dialogs.py (ThubanFrame.__init__): Handle
+	EVT_WINDOW_DESTROY
+	(ThubanFrame.OnDestroy): New. Handler for EVT_WINDOW_DESTROY. Does
+	nothing but is convenient for the derived classes.
+
+	* Thuban/UI/tableview.py
+	(TableFrame.OnDestroy, LayerTableFrame.OnDestroy): New.
+	Unsubscribe the messages here not in OnClose because that might
+	get called multiple times. Fixes RT #2196
+	(TableFrame.OnClose, LayerTableFrame.OnClose): Removed. Not needed
+	anymore.
+
+	* README: Update the minimum requirement for wxPython. Since we
+	now use the EVT_WINDOW_DESTROY event, we need at least 2.4.0.4,
+	the version in which that was introduced for all platforms
+
+2003-10-30  Frank Koormann <frank at intevation.de>
+
+	* Thuban/UI/join.py (JoinDialog.OnJoin): Wrapped the major parts of 
+	the join process in a ThubanBeginBusyCursor, ThubanEndBusyCursor
+	frame.
+
+2003-10-30  Jan-Oliver Wagner <jan at intevation.de>
+
+	Improved APR import extension, added further EPSG definitions
+	and some cleanup regarding string class.
+
+	* test/test_proj.py (TestProjection.test_get_projection_units_geo):
+	Added test for alias 'longlat'.
+
+	* Resources/Projections/epsg-deprecated.proj: New. Contains
+	deprecated EPSG definitions.
+
+	* Extensions/importAPR/odb.py (ODBBaseObject.TreeInfo): Added
+	the variable names for objects.
+
+	* Extensions/importAPR/apr.py (APR_BLnSym, APR_BMkSym, APR_BShSym): New.
+	Copied from importAPR and provided with documentation.
+
+	* Extensions/importAPR/importAPR.py (APR_BLnSym, APR_BMkSym, APR_BShSym):
+	Moved to apr.py.
+	(APR_View): Added object ref 'ITheme'.
+
+	* Thuban/Lib/fileutil.py, Thuban/UI/proj4dialog.py: Replaced string
+	split function by corresponding use of the string class method.
+
+	* Thuban/Model/xmlwriter.py: Replaced string replace function by
+	corresponding string method.
+
+2003-10-29  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/baserenderer.py
+	(BaseRenderer.draw_shape_layer_incrementally): Speed up the
+	special case of a classification that only has the default group
+
+2003-10-27  Bernhard Herzog  <bh at intevation.de>
+
+	* po/fr.po, po/es.po: Updated translations from Daniel Calvelo
+
+	* po/de.po: Update.
+
+	* Thuban/UI/application.py
+	(ThubanApplication.ShowExceptionDialog): Handle translation of the
+	dialog message properly
+
+2003-10-27  Bernhard Herzog  <bh at intevation.de>
+
+	Rework how localization works so that we use wx's translation
+	functions when running Thuban as a normal application but not when
+	we don't need any UI, such as in the test suite. See the comment
+	in Thuban/__init__.py for details
+
+	* Thuban/__init__.py (_): Add one level of indirection to make the
+	translation handling more flexible and to make it possible to use
+	either wx's translation services or not.
+	(gettext_identity, translation_function_installed)
+	(install_translation_function): New function to help with this
+
+	* Thuban/UI/__init__.py: Install the wx specific translation
+	function if it's OK to do that
+
+	* test/support.py (initthuban): Install a dummy translation
+	function so that importing Thuban.UI doesn't install a wx specific
+	one for which would need to import wxPython
+
+2003-10-27  Bernhard Herzog  <bh at intevation.de>
+
+	* HOWTO-Release: Source archives should be created first and the
+	binary packages should be created from the source archives.
+	There's an official debian package now so there's no need to test
+	the rpm on debian anymore
+
+2003-10-27  Bernhard Herzog  <bh at intevation.de>
+
+	Several rendering changes:
+
+	 - Render the selection into a separate bitmap so that only that
+	   bitmap needs to be redrawn when the selection changes
+
+	 - Render incrementally showing previews and allowing interaction
+	   before rendering is complete
+
+	 - Update the renderer interface a bit. Most parameters of
+	   RenderMap are now parameters of the constructor
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.__init__): Add the map
+	and the update region as parameters. Update the doc-string
+	(BaseRenderer.render_map_incrementally): New. Generator function
+	to renders the map incrementally
+	(BaseRenderer.render_map): Remove the map argument (it's now in
+	the constructor) and simply iterate over the
+	render_map_incrementally generator to draw the map.
+	(BaseRenderer.draw_shape_layer_incrementally)
+	(BaseRenderer.draw_shape_layer): Renamed to
+	draw_shape_layer_incrementally and changed into a generator that
+	yields True every 500 shapes. Used by render_map_incrementally to
+	render shape layers incrementally
+
+	* Thuban/UI/renderer.py (ScreenRenderer.RenderMap): Removed the
+	map and region parameters which are now in the constructor
+	(ScreenRenderer.RenderMapIncrementally): New. Public frontend for
+	the inherited render_map_incrementally.
+	(BaseRenderer.draw_shape_layer): Removed.
+	(ScreenRenderer.draw_selection_incrementally): New. The selection
+	drawing part of the removed draw_shape_layer as a generator
+	(ScreenRenderer.layer_shapes): Update because of the region
+	parameter change
+	(ExportRenderer.__init__): New. Extend the inherited constructor
+	with the destination region for the drawing
+	(ExportRenderer.RenderMap): Removed the map and region parameters
+	which are now in the constructor
+
+	* Thuban/UI/view.py (MapCanvas.PreviewBitmap): New. Return a
+	bitmap suitable for a preview in a tool
+	(CanvasPanTool.MouseMove): Use the PreviewBitmap method to get the
+	bitmap
+	(MapPrintout.draw_on_dc): Adapt to new renderer interface
+	(MapCanvas.OnPaint): Handle drawing the selection bitmap if it
+	exists
+	(MapCanvas.OnIdle): Update the logic to deal with incremental
+	rendering and the selection bitmap
+	(MapCanvas._do_redraw): Handle the instantiation of the render
+	iterator and the redraws during rendering
+	(MapCanvas._render_iterator): New. Generator to incrementally
+	redraw both bitmaps
+	(MapCanvas.Export): Adapt to new renderer interface.
+	(MapCanvas.full_redraw): Reset the selection bitmap and the
+	renderer iterator too
+	(MapCanvas.redraw_selection): New. Force a redraw of the selection
+	bitmap
+	(MapCanvas.shape_selected): Only redraw the selection bitmap
+
+	* test/test_baserenderer.py
+	(TestBaseRenderer.test_polygon_no_projection)
+	(TestBaseRenderer.test_raster_no_projection)
+	(TestBaseRenderer.test_point_map_projection)
+	(TestBaseRenderer.test_point_layer_and_map_projection)
+	(TestBaseRenderer.test_point_layer_projection)
+	(TestBaseRenderer.test_point_with_classification): Adapt to new
+	renderer interface
+
+2003-10-24  Bernhard Herzog  <bh at intevation.de>
+
+	* libraries/thuban/wxproj.cpp (draw_polygon_shape)
+	(point_in_polygon_shape, shape_centroid): Raise an exception if
+	the shape can't be read. Previously invalid shape ids would lead
+	to a segfault.
+
+	* test/test_wxproj.py (TestShapeCentroid.test_invalid_shape_id):
+	New. test whether an exception is raised for invalid shape ids
+
+2003-10-24  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/Model/proj.py (Projection.GetProjectedUnits): Added 'longlat'
+	as alias for 'latlong'.
+
+	* Thuban/UI/projdialog.py (ProjFrame.__init__): Added 'longlat'
+	as alias for 'latlong'.
+
+2003-10-24  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/projdialog.py (ProjFrame.proj_selection_changed): Set
+	the projection even for the UnknownPanel.
+	(UnknownProjPanel.__init__): Define the text and create the textctrl
+	widget.
+	(UnknownProjPanel._DoLayout): Replaced static text widget by the
+	textctrl created in __init__.
+	(UnknownProjPanel.SetProjection): Set the text for the text ctrl
+	including the parameters of the projection.
+	
+2003-10-24  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Resources/Projections/epsg.proj: New. This is a list of
+	EPSG codes with parameters for proj. The list has been
+	generated using devtools/create_epsg.py based on the
+	file nad/epsg of the proj 4.4.7 package. Four projection
+	definitions have been deleted as they are not accepted by proj:
+	"CH1903+ / LV95", "Bern 1898 (Bern) / LV03C", "CH1903 / LV03"
+	and "HD72 / EOV".
+
+2003-10-22  Bernhard Herzog  <bh at intevation.de>
+
+	Some more tweaks to the projection dialog which should fix RT
+	#1886.
+
+	* Thuban/UI/projlist.py (ProjectionList.Destroy): Unsubscribe from
+	the ProjFile's messages and call the base class methods correctly
+	(ProjectionList.SelectProjection): Set the wxLIST_STATE_FOCUSED
+	flag on the newly selected item too. Otherwise some other item is
+	focused and the first time the focus is moved with the keyboard
+	the selection moves in unexpected ways.
+
+	* Thuban/UI/projdialog.py (ProjFrame.__init__): Do not set the
+	focus on the OK button, only on the projection list. That way the
+	list really has the focus initially
+	(ProjFrame.OnClose): Call the projection list's Destroy method to
+	make it unsubscribe all messages
+
+2003-10-21  Bernhard Herzog  <bh at intevation.de>
+
+	Rework the projection dialog to fix a few bugs, including RT 2166
+	and most of 2168
+
+	* Thuban/UI/projlist.py: New. The class ProjectionList is a
+	special wxListCtrl to show a list of projections in a more MVC
+	fashion
+
+	* Thuban/UI/projdialog.py (ProjFrame): Substantial changes
+	throughout the class. The main change is to use the ProjectionList
+	class instead of a normal wxListBox. Also, add an explicit
+	"Unknown" projection to the projection choice control.
+	(ProjPanel.__init__): Add an "unknown" ellipsoid
+	(TMPanel.__init__, LCCPanel.__init__): Tweak the order of
+	instantiation of the panel's controls to make the tab-order more
+	natural
+
+2003-10-21  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_load.py (TestSingleLayer.file_contents)
+	(TestSingleLayer.test): Add non-ascii characters to the titles of
+	session, map and layer. This is effectively a port of the
+	TestUnicodeStrings test in test_load_0_8.py which for some reason
+	was only added there.
+
+	* test/test_load_0_9.py (TestSingleLayer.file_contents)
+	(TestSingleLayer.test): Same as in test_load.py: add non-ascii
+	characters to the titles of session, map and layer,.
+
+2003-10-21  Bernhard Herzog  <bh at intevation.de>
+
+	Add EPSG projection handling to .thuban files
+
+	* test/test_save.py (SaveSessionTest.dtd)
+	(SaveSessionTest.testEmptySession)
+	(SaveSessionTest.testLayerProjection)
+	(SaveSessionTest.testRasterLayer)
+	(SaveSessionTest.testClassifiedLayer)
+	(SaveSessionTest.test_dbf_table)
+	(SaveSessionTest.test_joined_table)
+	(SaveSessionTest.test_save_postgis): Update to 1.0-dev namespace
+	(SaveSessionTest.testSingleLayer): Update to 1.0-dev namespace and
+	use a and epsg projection to test saving them
+
+	* test/test_load.py (LoadSessionTest.dtd): Update to 1.0-dev
+	namespace
+	(TestLayerVisibility.file_contents, TestLabels.file_contents)
+	(TestLayerProjection.file_contents)
+	(TestRasterLayer.file_contents, TestJoinedTable.file_contents)
+	(TestPostGISLayer.file_contents)
+	(TestPostGISLayerPassword.file_contents)
+	(TestLoadError.file_contents, TestLoadError.test): Update to use
+	1.0-dev namespace
+	(TestSingleLayer.file_contents, TestSingleLayer.test): Update to
+	use 1.0-dev namespace and use an EPSG projection to test whether
+	loading it works
+
+	* test/test_load_0_9.py: New. Effectively a copy of test_load.py
+	as of Thuban 0.9. These are now tests to determine whether Thuban
+	can still read files generated by Thuban 0.9
+
+	* Thuban/Model/save.py (SessionSaver.write)
+	(SessionSaver.write_session): Use the 1.0 dtd and 1.0-dev
+	namespace
+	(SessionSaver.write_projection): Write the projection's epsg
+	attribute
+
+	* Thuban/Model/load.py (SessionLoader.__init__): Also accept the
+	thuban-1.0-dev.dtd namespace
+	(SessionLoader.check_attrs): Allow a callable object as conversion
+	too
+	(SessionLoader.start_projection, SessionLoader.end_projection)
+	(SessionLoader.start_parameter): Handle the epsg attribute and
+	rename a few instance variables to lower case
+
+	* Resources/XML/thuban-1.0.dtd: New. Only difference to
+	thuban-0.9.dtd is the epsg attribute for projections.
+
+2003-10-21  Bernhard Herzog  <bh at intevation.de>
+
+	* test/runtests.py (main): Let the user specify which tests to run
+	on the command line
+
+	* test/support.py (ThubanTestResult.getDescription): Override to
+	give a better short description. The description can be used as a
+	parameter to run_tests to run that particular test in isolation.
+
+2003-10-21  Frank Koormann   <frank at intevation.de>
+
+	Popup menu for legend. Scheduled for the 1.2 release this was too
+	simple to implement: The popup menu is bound to the legend tree, while
+	the events are hanlded by its anchestor, the legend panel. This
+	allows reuse of all the event handlers already implemented for the 
+	legend toolbar buttons.
+
+	* Thuban/UI/legend.py (LegendPanel.__init__): EVT_MENU macros 
+	to add handlers for the events issued by the popup menu.
+ 	(LegendPanel._OnToggleVisibility): Handler for toggling layer
+	visibility event
+    	(LegendPanel._OnProjection): Handler for layer projection event.
+	(LegendTree.__init__): Added EVT_TREE_ITEM_RIGHT_CLICK
+	(LegendTree._OnRightClick): Event handler for right click, select item
+	and pop up menu.
+	(LegendTree.ToggleVisibility): Toggle layer visibility
+	(LegendTree.LayerProjection): Raise layer projection dialog for
+	current layer.
+
+2003-10-21  Bernhard Herzog  <bh at intevation.de>
+
+	* Resources/Projections/defaults.proj: Use correct DOCTYPE
+	declaration. The top-level element is projectionlist not projfile
+
+2003-10-20  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/projdialog.py (ProjFrame.write_proj_file): New. helper
+	method to write a projfile and display a busy cursor and error
+	dialogs.
+	(ProjFrame._OnSave, ProjFrame._OnAddToList, ProjFrame._OnImport)
+	(ProjFrame._OnExport, ProjFrame._OnRemove): Use write_proj_file
+	(ProjFrame.__FillAvailList): Translate "<None>" too and display a
+	busy cursor while loading the user and system prj files.
+
+2003-10-16  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/resource.py (projfile_cache): Introduce a cache for
+	ProjFile objects
+	(clear_proj_file_cache): New function to clear the cache. Mainly
+	useful for use by the test suite
+	(read_proj_file): Use the cache.
+
+	* test/test_proj.py (TestProjFile): Clarify the doc-string
+	(ProjFileReadTests): Update doc-string
+	(ProjFileReadTests.test_get_system_proj_file): Check whether the
+	system proj files is cached.
+	(ProjFileLoadTestCase): New base class for the proj file tests
+	derived from support.FileLoadTestCase to provide some common
+	behavior.
+	(TestLoadingProjFile)
+	(TestLoadingProjFileWithEmptyProjectionlist.file_contents)
+	(TestProjFileWithInvalidParameters.file_contents): Derive from
+	ProjFileLoadTestCase
+	(TestLoadingProjFile.test_caching): New. Test whether the cache
+	works
+
+2003-10-16 	Silke Reimer	<silke at intevation.de>
+
+	* debian/*: New directory with configuration files for building a thuban
+	  deb-package.
+
+2003-10-14  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_proj.py: Execute support.run_tests when run as
+	__main__ so that missing unsubscribes are detected
+	(TestProjFile.tearDown): Destroy the proj_file properly
+
+2003-10-14  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/messages.py (PROJECTION_ADDED)
+	(PROJECTION_REPLACED, PROJECTION_REMOVED): New message types for
+	the ProjFile objects
+
+	* Thuban/Model/proj.py (ProjFile): Derive from Publisher so we can
+	easily send messages when the projections change
+	(ProjFile.Add, ProjFile.Remove, ProjFile.Replace): Issue messages
+	when the change was successful
+
+	* test/test_proj.py (TestProjFile.setUp): Subscribe to some of the
+	proj file messages
+	(TestProjFile.test_add_remove)
+	(TestProjFile.test_remove_non_existing)
+	(TestProjFile.test_replace)
+	(TestProjFile.test_replace_non_existing): Test whether the right
+	messages are sent
+
+2003-10-14  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_proj.py (TestProjFile.test): Refactor into several
+	tests
+	(TestProjFile.test_add_remove)
+	(TestProjFile.test_remove_non_existing)
+	(TestProjFile.test_replace)
+	(TestProjFile.test_replace_non_existing): Some of the new
+	individual test cases
+	(TestProjFileSimple): New class for the rest of the test cases
+	that came out of the refactoring
+	(ProjFileTest): Derive from xmlsupport.ValidationTest so that the
+	derived classes don't have to
+
+2003-10-13  Bernhard Herzog  <bh at intevation.de>
+
+	Add an optional EPSG code to the projection objects and extend the
+	.proj file format accordingly.
+
+	* Resources/XML/projfile.dtd (element projection): Add epsg
+	attribute
+
+	* Thuban/Model/proj.py (Projection.__init__): New parameter and
+	instance variable epsg. Update doc-string
+	(Projection.EPSGCode, Projection.Label): New methods to provide
+	access to EPSG code and a label for use in dialogs
+
+	* Thuban/Model/resource.py (ProjFileReader.start_projection)
+	(ProjFileReader.end_projection, ProjFileSaver.write_projfile):
+	Handle the epsg code attribute when reading or writing proj files
+
+	* Thuban/UI/projdialog.py (ProjFrame._OnSave)
+	(ProjFrame._OnAddToList, ProjFrame.__DoOnProjAvail)
+	(ProjFrame.__FillAvailList): Use the projection's Label method to
+	get the string for the list box
+
+	* test/test_proj.py (TestProjection.test_label)
+	(TestProjection.test_label_epsg)
+	(TestProjection.test_epsgcode_for_non_epsg_projection)
+	(TestProjection.test_epsgcode_for_real_epsg_projection): New tests
+	for the label and EPSGCode methods
+	(WriteProjFileTests.doTestWrite, WriteProjFileTests.test_write)
+	(WriteProjFileTests.test_write_empty_file): Create the ProjFile
+	objects in the test cases and put the expected contents into the
+	test case methods too. Update doTestWrite accordingly
+	(TestLoadingProjFile)
+	(TestLoadingProjFileWithEmptyProjectionlist): New classes with the
+	read tests from TestProjFile.
+	(TestProjFile.doTestRead, TestProjFile.testRead): Removed. These
+	tests are now in the new classes.
+	(sample_projfile, sample_projfile_data)
+	(sample_projfile2, sample_projfile_data2): Removed. Not used
+	anymore.
+	(TestProjFile.test_read_unreadable_file): No need to reset the
+	permissions at the end anymore since we use a unique filename
+
+2003-10-13  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_proj.py: Some more refactoring of the test cases
+	(ProjFileTest): New base class for the proj file tests.
+	(TestProjFile): Derive from ProjFileTest
+	(TestProjFile.test_read_unreadable_file)
+	(TestProjFile.test_read_empty_file, TestProjFile.doTestRead): Use
+	the new filename method to get a unique filename
+	(TestProjFile.doTestWrite, TestProjFile.testWrite): Removed.
+	(WriteProjFileTests): New class for proj file write tests.
+	Contains the write test that were in TestProjFile originally.
+
+2003-10-13  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_proj.py (TestProjFile.testRead)
+	(TestProjFile.test_read_non_existing_file)
+	(TestProjFile.test_read_unreadable_file)
+	(TestProjFile.test_read_empty_file): Split into several methods.
+
+2003-10-10  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/sizers.py: New file with custom sizers.
+
+	* Thuban/UI/projdialog.py (ProjFrame.build_dialog): Instantiate
+	all projection type specific panels and put them into a
+	NotebookLikeSizer. This way the dialog doesn't change its size
+	when a different projection is selected
+	(ProjFrame.__init__): Rename projection_panels
+	projection_panel_defs and reuse projection_panels for a list of
+	the instantiated panels.
+	(ProjFrame._show_proj_panel, ProjFrame.__DoOnProjAvail)
+	(ProjFrame.__DoOnProjChoice): Changes due to the new handling of
+	the panels
+	(UnknownProjPanel._DoLayout): Place the newlines in the message
+	differently to make the panel narrower.
+	(TMPanel._DoLayout): Layout the parameters in one column.
+
+2003-10-10  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/projdialog.py (ProjFrame.build_dialog): New method
+	that contains all the setup for the dialog's widgets, layout and
+	event handling.
+	(__): Call build_dialog to build the dialog.
+	(ProjFrame.__set_properties, ProjFrame.__do_layout): Removed.
+	Their functionality is now in build_dialog
+	(ProjFrame.__VerifyButtons, ProjFrame.__VerifyButtons)
+	(ProjFrame.__DoOnProjAvail, ProjFrame.__DoOnProjAvail)
+	(ProjFrame.__DoOnProjChoice): Small updates due to slightly
+	different widget names and hierarchy introduced with build_dialog.
+
+2003-10-10  Bernhard Herzog  <bh at intevation.de>
+
+	* README: Fix typo.
+
+2003-10-09  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/proj.py (ProjFile.Add): Do not check whether the
+	projection is already in the list. This is *a lot* faster when
+	loading files with hundreds of projections since it saves a linear
+	search. OTOH this will allow adding the same projection to the
+	user.proj file multiple times in the projection dialog but we'll
+	deal with that later
+
+2003-10-09  Jan-Oliver Wagner <jan at intevation.de>
+
+	* devtools: New. Directory for developer tools that are not intended
+	for the regular user.
+
+	* devtools/create_epsg.py: New. Convert the epsg file of proj into
+	a python .proj file.
+
+2003-10-09  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_proj.py
+	(TestProjection.test_get_parameter_without_equals_sign): New. Test
+	whether GetParameter handles parameters without "=" sign correctly
+
+	* Thuban/Model/proj.py (Projection.GetParameter): Handle
+	parameters that do not contain a "=". Update the doc-string
+
+2003-10-08  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/projdialog.py (ProjFrame.__set_properties): Remove the
+	length limit on the projname text control
+
+2003-10-08  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_proj.py (TestProjection.test_get_projection_units_geo)
+	(TestProjection.test_get_projection_units_normal): New. Tests for
+	the Projection.GetProjectedUnits method
+
+2003-10-08  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/Model/resource.py (get_user_proj_file): small bug-fix:
+	Added missing 'val' parameter.
+
+2003-10-08  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/projdialog.py (ProjFrame.__DoOnProjAvail): When the
+	projection type of the currently selected projection is not known,
+	i.e. there's no panel for it, use the UnknownProjPanel
+	(ProjFrame.__DoOnProjChoice, ProjFrame._show_proj_panel): Split
+	the actual replacing of the proj panel into the new method
+	_show_proj_panel.
+	(UnknownProjPanel): Add doc-string.
+	(UnknownProjPanel._DoLayout): Insert a newline into the text so
+	that the panel is not so wide.
+
+2003-10-08  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/resource.py (read_proj_file): Return the warnings
+	too. Update the doc-string
+	(get_proj_files): Removed. It wasn't used anywhere
+	(get_system_proj_files, get_system_proj_file): Rename to
+	get_system_proj_file and return the ProjFile object and not a list
+	of ProjFile objects. Update the callers.
+	(get_user_proj_files, get_user_proj_file): Rename to
+	get_user_proj_file return the ProjFile object and not a list of
+	ProjFile objects. Update the callers.
+	(ProjFileReader.__init__): New instance variable for the warnings.
+	Rename the __pf ivar to projfile. Update the methods referring to
+	__pf
+	(ProjFileReader.end_projection): Catch any errors raised when
+	instantiating the projection and record that as an error. The
+	projection will not be in the final ProjFile object.
+	(ProjFileReader.GetWarnings): New method to return the warnings.
+
+	* Thuban/UI/projdialog.py (ProjFrame.show_warnings): New method to
+	show the warnings from the projfile reader
+	(ProjFrame._OnImport): Deal with any warnings returned by
+	read_proj_file
+	(ProjFrame.__FillAvailList): Deal with any warnings returned by
+	get_system_proj_file or get_user_proj_file.
+
+	* test/test_proj.py (TestProjFile.doTestRead): Check the warnings.
+	(TestProjFileWithInvalidParameters.file_contents): New test cases
+	to test whether read_proj_file handles invalid projection
+	parameters correctly
+	(TestProjFile.test_get_system_proj_file): New. Simple test for
+	resource.get_system_proj_file
+
+2003-10-07  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_derivedshapestore.py
+	(TestDerivedShapeStoreExceptions.tearDown): Clear the session
+	properly so that the temporary directories get deleted correctly
+
+2003-10-06  Bernhard Herzog  <bh at intevation.de>
+
+	Handle the title changes in a proper MVC way.
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): Subscribe to the
+	canvas' TITLE_CHANGED messages
+	(MainWindow.update_title): New. Update the main window's title
+	(MainWindow.__SetTitle): Removed. Use update_title instead.
+	(MainWindow.SetMap): Use update_title instead of __SetTitle
+	(MainWindow.RenameMap): Do change the window title explicitly
+	here. That's handled in a proper MVC way now.
+	(MainWindow.title_changed): New. Subscriber for the TITLE_CHANGED
+	messages
+
+	* Thuban/Lib/connector.py (Conduit): New class to help classes
+	that forward messages
+
+	* Thuban/UI/viewport.py: Forward the map's TITLE_CHANGED messages
+	(ViewPort): Derive from Conduit instead of Publisher
+	(ViewPort.Subscribe, ViewPort.Unsubscribe): Use the new base class
+	when calling the inherited versions
+	(ViewPort._subscribe_map, ViewPort._unsubscribe_map): New helper
+	methods to subscribe and unsubscribe map messages
+	(ViewPort.SetMap, ViewPort.Destroy): Use the new helper methods to
+	handle the map subscriptions
+	(ViewPort.Map, ViewPort.map_projection_changed) 
+	(ViewPort.layer_projection_changed): Add or update doc-strings
+
+	* test/test_connector.py (TestPublisher.test_issue_simple): Fix
+	typo
+	(MyConduit): Helper class for the Conduit test.
+	(TestConduit): Test cases for Conduit
+
+	* test/test_connector.py: Use support.run_tests as main.
+
+	* test/test_viewport.py (ViewPortTest.setUp): Also subscribe to
+	the TITLE_CHANGED messages
+	(ViewPortTest.test_forwarding_title_changed): New test to check
+	whether the viewport forwards the map's TITLE_CHANGED messages
+	(TestViewportWithPostGIS.tearDown): Call the map's Destroy method
+	after the port's because the latter may require a still functional
+	map.
+
+2003-10-06  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/application.py (ThubanApplication.maps_changed): Add
+	doc-string
+
+2003-10-06  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_viewport.py (ViewPortTest.setUp)
+	(SimpleViewPortTest.test_init_with_size): Move the test for the
+	initial size as a constructor parameter from ViewPortTest.setUp
+	method to a new separate test in SimpleViewPortTest.
+
+2003-10-06  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_viewport.py (MockView): New class derived from
+	ViewPort with a mock implementation of GetTextExtent to be used in
+	the test cases
+	(ViewPortTest.setUp): Use MockView instead of ViewPort
+
+	* Thuban/UI/viewport.py (ViewPort.GetTextExtent): Turn this method
+	into what would be a "pure virtual function" in C++: always raise
+	NotImplementedError. Mock implementations for test cases don't
+	belong into the real code
+
+2003-10-02  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_layer.py (TestLayer.test_empty_layer): Explicitly
+	close the dbf file we create so that it's contents have been
+	written properly.
+
+	* libraries/shapelib/shptree.c, libraries/shapelib/shpopen.c,
+	libraries/shapelib/shapefil.h, libraries/shapelib/dbfopen.c:
+	Update to shapelib 1.2.10
+
+2003-10-01  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/tree.py, Thuban/UI/main.py: Remove the #! line as
+	it annoys lintian which warns about these files not being
+	executable. The #! isn't necessary here since if you absolutely
+	must execute them you can always say "python <filename>".
+
+2003-09-26  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/classgen.py (GenQuantiles0): Removed since it's
+	only used in GREAT-ER but not used in Thuban itself. When GREAT-ER
+	is ported to a newer the import will fail, so it should be noticed
+	immediately that this function is gone.
+	Fixes RT#1919
+
+2003-09-26  Bernhard Herzog  <bh at intevation.de>
+
+	Add a DTD for the projection files and make thuban write valid
+	projection files
+
+	* Resources/XML/projfile.dtd: New. DTD for thuban's projection
+	files
+
+	* Thuban/Model/resource.py (ProjFileSaver.write): Use
+	'projectionlist' as the name in the document type declaration so
+	that it matches the element type of the root element.
+
+	* test/test_proj.py (sample_projfile, sample_projfile2): Use
+	'projectionlist' as the name in the document type declaration just
+	as it is done now in the files thuban would write
+	(sample_projfile, sample_projfile_data): Fix spelling of
+	"Mercator"
+	(TestProjFile.doTestWrite): Validate the written and the expected
+	XML data
+	(TestProjFile): Derive from ValidationTest so that we can run xml
+	validation tests
+
+2003-09-24  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/renderer.py (ExportRenderer.render_legend): Do not
+	modify the list returned by map.Layers() in place since it is the
+	actual list of layers used by the map.
+
+2003-09-23  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Added subsection to chapter
+	Extensions to describe the extensions coming with the Thuban
+	standard package (gns2shp and importAPR).
+
+2003-09-23  Bernhard Herzog  <bh at intevation.de>
+
+	* libraries/thuban/wxproj.cpp (project_point): if there's an
+	inverse but no forward projection, convert to degrees after
+	applying the inverse projection. Fixes RT#2096
+
+	* test/test_wxproj.py: New. Test cases for wxproj.so. One test
+	implicitly tests for the fix to RT#2096
+
+	* test/support.py (FloatComparisonMixin.assertFloatSeqEqual):
+	Check that the sequences have the same lengths
+
+	* Resources/Projections/defaults.proj (Geographic projection): Use
+	a much more precise value for the to_meter attribute.
+
+2003-09-22  Bernhard Herzog  <bh at intevation.de>
+
+	* test/support.py (initthuban): Make sure to unset the LANG env.
+	var. so that tests that compare translated strings work. Solves RT
+	#2094
+
+2003-09-22  Jan-Oliver Wagner <jan at intevation.de>
+
+	Small improvement of APR import.
+
+	* Extensions/importAPR/test/test_apr.py (aprTest.test_LClass): 
+	Added tests for text-ranges.
+
+	* Extensions/importAPR/apr.py (APR_LClass.GetThubanRange): Now
+	returns a string object if the range is based on text.
+
+	* Extensions/importAPR/importAPR.py (import_apr_dialog): Unified
+	range retrieval.
+
+2003-09-22  Jan-Oliver Wagner <jan at intevation.de>
+
+	Initial version of the importAPR extension which is in
+	experimental state.
+
+	* /Extensions/importAPR/, /Extensions/importAPR/samples/,
+	/Extensions/importAPR/test/: New directories.
+
+	* /Extensions/importAPR/samples/README: New: Howto load the samples.
+
+	* /Extensions/importAPR/samples/iceland.apr: New: A sample APR
+	file which refers to the Thuban Iceland demo data.
+
+	* /Extensions/importAPR/test/README: New: Howto execute the tests.
+
+	* /Extensions/importAPR/test/test_apr.py: New: Tests for APR classes.
+
+	* /Extensions/importAPR/apr.py: New: Classes for ArcView Objects
+	as in '.apr'-files.
+
+	* /Extensions/importAPR/odb.py: New: Classes for generic ArcView
+	ODB Objects as in '.apr', '.avl' and other files.
+
+	* /Extensions/importAPR/__init__.py: New: Init to make this
+	directory a package.
+
+	* /Extensions/importAPR/importAPR.py: New: Import a ArcView
+	project file (.apr) and convert it to Thuban.
+
+2003-09-22  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Extensions/gns2shp.gns2shp.py: The main module of gns2shp.
+
+2003-09-19  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Extended section 'Installation'
+	with description on RPM installation and RPM binary package
+	creation.
+
+2003-09-18  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (data_files): Only add the mo files if the Locales
+	directory actually exists, so that setup.py works with a fresh CVS
+	checkout
+
+2003-09-12  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Examples/simple_extensions/simple_tool.py: bugfix: Tool is now
+	in viewport, not anymore in view
+
+2003-09-04  Jan-Oliver Wagner <jan at intevation.de>
+
+	Introducing first Extension (gns2shp).
+
+	* Extensions, Extensions/gns2shp, Extensions/gns2shp/test: New.
+
+	* Extensions/__init__.py: New. init to make this dir a package.
+
+	* Extensions/gns2shp/__init__.py: New. init to make this dir a package.
+
+	* Extensions/gns2shp/test/README: New. some info on this test directory.
+
+	* Extensions/gns2shp/test/ls.txt: New. test data set (Liechtenstein).
+
+	* Extensions/gns2shp/test/test_gns2shp.py: New. Test for correct creation
+	of Shapefile from GNS text file format
+
+2003-09-03  Jan-Oliver Wagner <jan at intevation.de>
+
+	Fix/workaround for bug #2019:
+	https://intevation.de/rt/webrt?serial_num=2019
+
+	* Thuban/UI/identifyview.py (IdentifyView.ID_STOP): New.
+	(IdentifyView.__init__): Added another button that allows to
+	stop the identify mode.
+	(IdentifyView.OnStop): New. Stops the identify mode.
+
+2003-09-03  Jan-Oliver Wagner <jan at intevation.de>
+
+	Introducing a new exception dialog that allows to exit the
+	application immediately.
+	This fixes bug #2060: https://intevation.de/rt/webrt?serial_num=2060
+
+	* Thuban/UI/exceptiondialog.py: New. A special exception dialog.
+
+	* Thuban/UI/application.py (ThubanApplication.ShowExceptionDialog):
+	Made strings available to translations. Exchanged the simple
+	ScrolledMessageDialog by the new ExceptionDialog.
+
+2003-09-01  Bernhard Herzog  <bh at intevation.de>
+
+	* NEWS: New. Summary of changes and release notes.
+
+	* MANIFEST.in: Add NEWS
+
+2003-09-01  Bernhard Herzog  <bh at intevation.de>
+
+	* MANIFEST.in: Correct the include statement for the mo-files and
+	include the documentation too.
+
+	* setup.py (data_files): Add the .mo files
+	(setup call): Up to version 0.9.0
+
+2003-09-01  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/dbdialog.py (ChooseDBTableDialog.__init__): Change the
+	parameter list to just parent and session
+	(ChooseDBTableDialog.__set_properties): Removed. Setting the
+	selection of empty list boxes is not allowed (and produces C++
+	assertion errors) and the rest of the setup is better done in
+	__init__ anyway.
+	(ChooseDBTableDialog.OnCancel, ChooseDBTableDialog.OnOK)
+	(ChooseDBTableDialog.OnLBDClick, DBDialog.OnOK): Use the Python
+	builtins True/False for booleans to avoid warnings from wxPython
+
+	* Thuban/UI/mainwindow.py (MainWindow.AddDBLayer): Adapt to new
+	ChooseDBTableDialog constructor parameters.
+
+2003-09-01  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/postgisdb.py
+	(PostGISTable): Extend doc-string
+	(PostGISTable._fetch_table_information): Set the column index
+	correctly, pretending ignored columns don't exist.
+
+	* test/test_postgis_db.py (TestPostGISIgnoredColumns): New tests
+	for postgis tables with data types not yet supported by thuban.
+
+2003-08-29  Bernhard Herzog  <bh at intevation.de>
+
+	* HOWTO-Release: Tweak item about running the tests.
+
+2003-08-29  Jan-Oliver Wagner <jan at intevation.de>
+
+	* /Doc/manual/thuban-manual.xml: updated to version 1.0pre2.
+
+2003-08-29  Bernhard Herzog  <bh at intevation.de>
+
+	Add some missing parameters to projections. Proj complains about
+	them on windows but for some reason not on Linux.
+
+	* test/test_save.py (SaveSessionTest.testLayerProjection): Add
+	missing required projection parameters
+
+	* test/test_proj.py (TestProjFile.test): Add missing required
+	projection parameters
+
+	* test/test_load_0_8.py (TestLayerProjection.file_contents)
+	(TestLayerProjection.test): Add missing required projection
+	parameters and tests for them
+
+	* test/test_load.py (TestLayerProjection.file_contents)
+	(TestLayerProjection.test): Add missing required projection
+	parameters and tests for them
+
+	* test/test_layer.py (TestLayer.test_base_layer): Add missing
+	required projection parameters
+
+2003-08-29  Bernhard Herzog  <bh at intevation.de>
+
+	* libraries/pyprojection/Projection.i: Use pj_get_errno_ref to
+	access the pj_errno because directly accessing pj_errno doesn't
+	work on windows if the proj library is in a DLL
+
+	* libraries/pyprojection/Projection_wrap.c: Update from Projection.i
+
+2003-08-28  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_proj.py: Import things from Thuban after calling
+	initthuban
+
+	* test/test_load.py (LoadSessionTest.filenames): New class
+	variable with the filename attributes to normalize
+	(LoadSessionTest.check_format): Pass self.filenames to
+	sax_eventlist to normalize the filename attributes
+
+	* test/xmlsupport.py: Add cvs keywords
+	(SaxEventLister.__init__): New parameter filenames which indicates
+	attributes that contain filenames
+	(SaxEventLister.startElementNS): Normalize the filename attributes
+	with os.path.normpath
+	(sax_eventlist): New parameter filenames to pass through to
+	SaxEventLister
+
+	* test/test_derivedshapestore.py: Make this file callable as a
+	program to execute the tests
+	(TestDerivedShapeStoreExceptions.test_table_with_wrong_size): Bind
+	the session to self.session so that it gets destroyed properly
+
+	* test/test_layer.py (TestLayer.tearDown): Call the session's
+	Destroy method
+
+	* test/test_map.py (TestMapBase.tearDown): Destroy self.session
+	too if it exists
+	(TestMapAddLayer.test_add_layer): Bind the session to self.session
+	so that it gets destroyed properly
+
+	* test/postgissupport.py (reason_for_not_running_tests): Add a
+	test for the existence of popen2.Popen4.
+
+	* test/test_save.py (SaveSessionTest.tearDown): New. Provide a
+	reliable way to destroy the sessions created in the test cases
+	(SaveSessionTest.test_dbf_table): Bind the session to self.session
+	so that it gets destroyed properly
+	(SaveSessionTest.testLayerProjection): Bind the session to
+	self.session so that it gets destroyed properly
+
+	* test/test_session.py (UnreferencedTablesTests.tearDown): Make
+	sure that the session is destroyed properly
+
+	* test/test_shapefilestore.py: Make this callable as a program to
+	execute the tests
+
+	* test/test_scalebar.py: Remove unnecessary import of _ from
+	Thuban
+
+	* test/support.py (print_garbage_information): Call initthuban
+	here because it may be called indirectly from test cases that test
+	test support modules which do not use anything from thuban itself
+	(ThubanTestProgram.runTests): Remove unnecessary debug print
+
+2003-08-28  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/version.py (longversion): Update to 0.9
+
+	* Thuban/UI/mainwindow.py: Remove some unused imports
+
+	* README: Add section about required additional software. Add date
+	and revision CVS keywords
+
+	* HOWTO-Release: Add item about the translations. Add date and
+	revision CVs keywords and change formatting to match README a bit
+	better
+
+	* po/de.po: Update for 0.9
+
+	* test/README: Tweak the wording a little because many tests are
+	not really unittest.
+
+2003-08-27  Bernhard Herzog  <bh at intevation.de>
+
+	As preparation for the 0.9 release, switch thuban files to a
+	non-dev namespace
+
+	* Thuban/Model/save.py (SessionSaver.write_session): Write files
+	with the http://thuban.intevation.org/dtds/thuban-0.9.dtd
+	namespace
+
+	* Thuban/Model/load.py (SessionLoader.__init__): Accept the
+	http://thuban.intevation.org/dtds/thuban-0.9.dtd namespace too
+
+	* test/test_save.py (SaveSessionTest.dtd)
+	(SaveSessionTest.testEmptySession)
+	(SaveSessionTest.testSingleLayer)
+	(SaveSessionTest.testLayerProjection)
+	(SaveSessionTest.testRasterLayer)
+	(SaveSessionTest.testClassifiedLayer)
+	(SaveSessionTest.test_dbf_table)
+	(SaveSessionTest.test_joined_table)
+	(SaveSessionTest.test_save_postgis): Update for new namespace
+
+	* test/test_load.py (LoadSessionTest.dtd, TestSingleLayer)
+	(TestLayerVisibility.file_contents, TestLabels.file_contents)
+	(TestLayerProjection.file_contents)
+	(TestRasterLayer.file_contents, TestJoinedTable.file_contents)
+	(TestPostGISLayer.file_contents)
+	(TestPostGISLayerPassword.file_contents)
+	(TestLoadError.file_contents, TestLoadError.test): Update for new
+	namespace
+
+2003-08-27  Bernhard Herzog  <bh at intevation.de>
+
+	Make the table interface distinguish between row ids (an integer
+	that uniquely identifies a row) and row ordinals (a simple row
+	count from 0 to NumRows() - 1)
+
+	* Thuban/Model/postgisdb.py (PostGISTable.RowIdToOrdinal)
+	(PostGISTable.RowOrdinalToId): New methods to conver between row
+	ids and row ordinals
+	(PostGISTable.ReadRowAsDict, PostGISTable.ReadValue): New keyword
+	parameter row_is_ordinal to indicate whether the row parameter is
+	the row id or the ordinal
+
+	* Thuban/Model/transientdb.py (TransientTableBase.RowIdToOrdinal)
+	(TransientTableBase.RowOrdinalToId)
+	(AutoTransientTable.RowIdToOrdinal)
+	(AutoTransientTable.RowOrdinalToId): Same new methods as in
+	PostGISTable.
+	(TransientTableBase.ReadRowAsDict, TransientTableBase.ReadValue)
+	(AutoTransientTable.ReadRowAsDict, AutoTransientTable.ReadValue):
+	Same new parameter as in PostGISTable.
+
+	* Thuban/Model/table.py (DBFTable.RowIdToOrdinal)
+	(DBFTable.RowOrdinalToId, MemoryTable.RowIdToOrdinal)
+	(MemoryTable.RowOrdinalToId): Same new methods as in PostGISTable.
+	(DBFTable.ReadValue, DBFTable.ReadRowAsDict)
+	(MemoryTable.ReadValue, MemoryTable.ReadRowAsDict): Same new
+	parameter as in PostGISTable.
+
+	* Thuban/UI/tableview.py (DataTable.RowIdToOrdinal)
+	(DataTable.RowOrdinalToId): New methods to convert between row ids
+	and row ordinals.
+	(TableGrid.SelectRowById): New method to select a row based on its
+	ID as opposed to its ordinal
+	(DataTable.GetValue, TableGrid.OnRangeSelect)
+	(TableGrid.OnSelectCell, LayerTableGrid.select_shapes)
+	(QueryTableFrame.OnQuery, QueryTableFrame.get_selected)
+	(LayerTableFrame.__init__): Convert between row ids and row
+	ordinals as appropriate
+
+	* test/postgissupport.py (PostGISDatabase.__init__): Add
+	doc-string.
+	(PostGISDatabase.initdb): The optional third item in a tuple in
+	tables is now a (key, value) list with additional arguments to
+	pass to upload_shapefile
+	(upload_shapefile): New parameter gid_offset to allow gids that
+	are not the same as the shapeids in the shapefile
+	(PostgreSQLServer.get_default_static_data_db): Use the new
+	gid_offset to make the gids in landmarks 1000 higher than the
+	shapeids in the shapefile
+
+	* test/test_viewport.py
+	(TestViewportWithPostGIS.test_find_shape_at_point): Adapt to the
+	new shapeids in the landmarks table
+
+	* test/test_transientdb.py
+	(TestTransientTable.run_iceland_political_tests)
+	(TestTransientTable.test_transient_joined_table): Add tests for
+	the new table methods and new keywords arguments.
+
+	* test/test_postgis_db.py
+	(TestPostGISTable.test_read_row_as_dict_row_count_mode)
+	(TestPostGISTable.test_read_value_row_count_mode)
+	(TestPostGISTable.test_row_id_to_ordinal)
+	(TestPostGISTable.test_row_oridnal_to_id): New test for the new
+	table methods and the new arguments
+	(TestPostGISShapestorePoint.test_shapes_in_region)
+	(TestPostGISShapestorePoint.test_shape_raw_data)
+	(TestPostGISShapestorePoint.test_shape_points)
+	(TestPostGISShapestorePoint.test_shape_shapeid)
+	(TestPostGISShapestorePoint.test_all_shapes)
+	(TestPostGISTable.test_simple_query)
+	(TestPostGISTable.test_simple_query)
+	(TestPostGISTable.test_simple_query)
+	(TestPostGISTable.test_read_value)
+	(TestPostGISTable.test_read_row_as_dict): Adapt to the new
+	shapeids in the landmarks table
+
+	* test/test_memory_table.py
+	(TestMemoryTable.test_read_row_as_dict_row_count_mode)
+	(TestMemoryTable.test_read_value_row_count_mode)
+	(TestMemoryTable.test_row_id_to_ordinal)
+	(TestMemoryTable.test_row_oridnal_to_id): New test for the new
+	table methods and the new arguments
+
+	* test/test_dbf_table.py
+	(TestDBFTable.test_read_row_as_dict_row_count_mode)
+	(TestDBFTable.test_read_value_row_count_mode)
+	(TestDBFTable.test_row_id_to_ordinal)
+	(TestDBFTable.test_row_oridnal_to_id): New test for the new table
+	methods and the new arguments
+
+2003-08-26  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/postgisdb.py (PostGISShapeStore.BoundingBox): Use a
+	more postgis specific but much faster method to get the bounding
+	box
+
+2003-08-26  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/postgisdb.py (PostGISTable.Title)
+	(PostGISShapeStore.AllShapes): Add these missing methods.
+	(PostGISShapeStore.ShapesInRegion): No need to raise
+	StopIteration. We can simply return
+
+	* test/test_postgis_db.py (TestPostGISTable.test_title)
+	(TestPostGISShapestorePoint.test_all_shapes): New tests for the
+	new methods
+
+2003-08-25  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/postgisdb.py (shapetype_map): Add MUTLIPOLYGON.
+
+	* test/test_postgis_db.py (PolygonTests): New class containing
+	those tests from TestPostGISShapestorePolygon that can also be
+	used to test MUTLIPOLYGON tables
+	(TestPostGISShapestorePolygon): Most tests are now in PolygonTests
+	so derive from that
+	(TestPostGISShapestoreMultiPolygon): New class with tests for
+	MUTLIPOLYGON tables
+
+	* test/postgissupport.py (PostGISDatabase.initdb): Allow the
+	tables argument to have tuples with three items to override the
+	WKT type used.
+	(PostgreSQLServer.get_default_static_data_db): Use the above to
+	create a polygon table with MUTLIPOLYGONs
+	(point_to_wkt, coords_to_point, polygon_to_wkt, coords_to_polygon)
+	(arc_to_wkt, coords_to_multilinestring): Rename from *_to_wkt to
+	coords_to*
+	(coords_to_multipolygon): New. Convert to MUTLIPOLYGON
+	(wkt_converter): New. Map WKT types to converters
+	(upload_shapefile): New parameter force_wkt_type to use a
+	different WKT type than the default
+
+2003-08-25  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/application.py
+	(ThubanApplication.run_db_param_dialog): New. Suitable as a
+	db_connection_callback. Main difference is that the dialog run
+	from this method doesn't have a parent so it can be used even when
+	there is no main window
+	(ThubanApplication.OpenSession): Use self.run_db_param_dialog if
+	no db_connection_callback was given. This way the dialog pops up
+	even when the .thuban file was given as a command line parameter.
+
+2003-08-25  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py (MapCanvas.OnLeftUp): Release the the mouse
+	before calling MouseLeftUp. MouseLeftUp may pop up modal dialogs
+	which leads to an effectively frozen X session because the user
+	can only interact with the dialog but the mouse is still grabbed
+	by the canvas.
+	Also, call the tool's Hide method before MouseLeftUp because
+	MouseLeftUp may change the tool's coordinates.
+
+2003-08-25  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/application.py (ThubanApplication.OpenSession): Catch
+	LoadCancelled exceptions and handle them by returning immediately.
+
+2003-08-25  Bernhard Herzog  <bh at intevation.de>
+
+	GUI part of loading sessions with postgis connections which may
+	require user interaction to get passwords or updated parameters
+
+	* Thuban/UI/dbdialog.py (DBDialog): Reimplement to make it look a
+	bit nucer and be more generic.
+	(DBFrame.OnAdd): Adapt to new DBDialog interface
+
+	* Thuban/UI/application.py (ThubanApplication.OpenSession): New
+	optional parameter db_connection_callback which is passed to
+	load_session.
+
+	* Thuban/UI/mainwindow.py (MainWindow.run_db_param_dialog): New.
+	Suitable as a db_connection_callback
+	(MainWindow.OpenSession): Use self.run_db_param_dialog as the
+	db_connection_callback of the application's OpenSession method
+
+
+2003-08-25  Bernhard Herzog  <bh at intevation.de>
+
+	Basic loading of sessions containing postgis connections:
+
+	* Thuban/Model/load.py (LoadError): Add doc-string
+	(LoadCancelled): New exception class to indicate a cancelled load
+	(SessionLoader.__init__): Add the db_connection_callback parameter
+	which will be used by the loader to get updated parameters and a
+	password for a database connection
+	(SessionLoader.__init__): Add the new XML elements to the
+	dispatchers dictionary
+	(SessionLoader.check_attrs): Two new conversions, ascii to convert
+	to a byte-string object and idref as a generic id reference
+	(SessionLoader.start_dbconnection)
+	(SessionLoader.start_dbshapesource): New. Handlers for the new XML
+	elements
+	(load_session): Add the db_connection_callback to pass through the
+	SessionLoader
+
+	* test/test_load.py (TestPostGISLayer, TestPostGISLayerPassword):
+	New classes to test loading of sessions with postgis database
+	connections.
+
+2003-08-25  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (__ThubanVersion__): Remove this and
+	replace it and the comment with __BuildDate__ by the Source: and
+	Id: cvs keywords as used in the other files.
+
+2003-08-25  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/load.py (SessionLoader.check_attrs): Raise a
+	LoadError when a required attribute is missing. The code used to
+	be commented out for some reason, but probably should have been
+	active.
+
+	* test/test_load.py (TestLoadError.test): Test the message in the
+	LoadError too to make sure it really is about the missing
+	attribute
+
+2003-08-22  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_save.py (SaveSessionTest.test_dbf_table) 
+	(SaveSessionTest.test_joined_table): Add XML validation tests.
+
+2003-08-22  Bernhard Herzog  <bh at intevation.de>
+
+	Implement saving a session with a postgis connection
+
+	* Resources/XML/thuban-0.9.dtd (dbconnection, dbshapesource) New
+	elements for database connections and shapestores using db
+	connections
+	(session): Add the dbconnections to the content model
+
+	* Thuban/Model/save.py (SessionSaver.write_db_connections): New.
+	Write the db connections
+	(SessionSaver.write_session): Call write_db_connections to write
+	the connection before the data sources
+	(SessionSaver.write_data_containers): Handle postgis shapestores
+
+	* test/test_save.py (SaveSessionTest.thubanids)
+	(SaveSessionTest.thubanidrefs): Update for new DTD
+	(SaveSessionTest.test_save_postgis): New. Test saving a session
+	with postgis connections
+
+	* Thuban/Model/postgisdb.py (PostGISTable.DBConnection)
+	(PostGISTable.TableName): New accessor methods for the connection
+	and table name
+
+	* test/test_postgis_db.py (TestPostGISTable.test_dbconn)
+	(TestPostGISTable.test_dbname): New methods to test the new
+	PostGISConnection methods
+
+2003-08-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/postgisdb.py (ConnectionError): New exception class
+	for exceptions occurring when establishing a Database connection
+	(PostGISConnection.connect): Catch psycopg.OperationalError during
+	connects and raise ConnectionError.
+
+	* test/test_postgis_db.py (TestPostgisDBExceptions): New class for
+	tests for database exceptions
+
+2003-08-22  Bernhard Herzog  <bh at intevation.de>
+
+	Prepare the test suite for tests with required authentication
+
+	* test/postgissupport.py (PostgreSQLServer.__init__): Add instance
+	variables with two predefined users/passwords, one for the admin
+	and one for a non-privileged user.
+	(PostgreSQLServer.createdb): Pass the admin name to initdb and add
+	the non-privileged user to the database and set the admin password
+	(PostgreSQLServer.wait_for_postmaster): Use the admin user name.
+	Better error reporting
+	(PostgreSQLServer.connection_params)
+	(PostgreSQLServer.connection_string): New methods to return
+	information about how to connect to the server
+	(PostgreSQLServer.execute_sql): New. Convenience method to execute
+	SQL statements
+	(PostgreSQLServer.require_authentication): Toggle whether the
+	server requires authentication
+	(PostgreSQLServer.create_user, PostgreSQLServer.alter_user): New.
+	Add or alter users
+	(PostGISDatabase.initdb): Pass the admin name one the
+	subprocesses' command lines. Grant select rights on
+	geometry_columns to everybody.
+	(upload_shapefile): Use the admin name and password when
+	connecting. Grant select rights on the new table to everybody.
+
+	* test/test_viewport.py (TestViewportWithPostGIS.setUp): Use the
+	server's new methods to get the connection parameters.
+
+	* test/test_postgis_session.py (TestSessionWithPostGIS.setUp)
+	(TestSessionWithPostGIS.test_remove_dbconn_exception): Use the
+	server's new methods to get the connection parameters.
+
+	* test/test_postgis_db.py
+	(TestPostGISConnection.test_gis_tables_empty)
+	(TestPostGISConnection.test_gis_tables_non_empty)
+	(PostGISStaticTests.setUp): Use the server's new methods to get
+	the connection parameters.
+
+2003-08-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/about.py (About.__init__): Add the psycopg version.
+
+	* Thuban/version.py: Add psycopg version
+
+	* Thuban/Model/postgisdb.py (psycopg_version): New. Return the
+	version of the psycopg module
+
+2003-08-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/dbdialog.py (DBPwdDlg): Removed because it's not used.
+	(DBFrame.OnEdit): Removed because it's not used and wouldn't work
+	at the moment. The functionality should probably be implemented
+	some time, though.
+	(DBFrame.OnRemove): Display a message if the connection can't be
+	removed because it's still in use.
+
+2003-08-22  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/about.py (About.__init__): split up the huge about
+	text into elements/lists for easier translation. This fixes bug
+	https://intevation.de/rt/webrt?serial_num=2058
+	Also, made some forgotten string available for the i18n.
+
+2003-08-21  Bernhard Herzog  <bh at intevation.de>
+
+	Make postgis support really optional including insensitive menu
+	items.
+
+	* Thuban/Model/postgisdb.py (has_postgis_support): New. Return
+	whether the postgis is supported.
+
+	* Thuban/UI/dbdialog.py: Put the psycopg import into try..except
+	to make postgis support optional
+
+	* Thuban/UI/mainwindow.py (_has_postgis_support): New. Context
+	version of Thuban.Model.postgisdb.has_postgis_support
+	(database_management command): Make it only sensitive if postgis
+	is supported.
+
+2003-08-21  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Added CVS revision for rev-history.
+	(section Adding and Removing Layers): Added text and described
+	multi-selection.
+	(chapter Extensions): New.
+
+2003-08-21  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.AddLayer): Changed dialog
+	settings to allow multiple files to load into the map.
+	Also reduced selection to *.shp as a default.
+
+2003-08-20  Bernhard Herzog  <bh at intevation.de>
+
+	Add dialogs and commands to open database connections and add
+	database layers.
+
+	* Thuban/UI/mainwindow.py (MainWindow.DatabaseManagement): New
+	method to open the database connection management dialog
+	(MainWindow.AddDBLayer): New method to add a layer from a database
+	(_has_dbconnections): New helper function to use for sensitivity
+	(database_management command, layer_add_db command): New commands
+	that call the above new methods.
+	(main_menu): Add the new commands to the menu.
+
+	* Thuban/Model/postgisdb.py (PostGISConnection.__init__)
+	(PostGISConnection.connect): Establish the actual connection in a
+	separate method and call it in __init__. This makes it easier to
+	override the behavior in test cases
+	(PostGISConnection.BriefDescription): New method to return a brief
+	description for use in dialogs.
+
+	* test/test_postgis_db.py (NonConnection): DB connection that
+	doesn't actually connect
+	(TestBriefDescription): New class with tests for the new
+	BriefDescription method
+
+2003-08-19  Jan-Oliver Wagner <jan at intevation.de>
+
+	Moved anything from extensions to libraries.
+
+	* libraries: New.
+
+	* libraries/ pyprojection, pyshapelib, shapelib, thuban: New.
+
+	* libraries/pyprojection/ LICENSE, MANIFEST.in, Projection.i,
+	Projection.py, Projection_wrap.c, setup.py, swighelp.txt: These files have
+	been moved here from thuban/extensions/pyprojection/
+	See there in the Attic for the older history.
+
+	* libraries/pyshapelib/ COPYING, ChangeLog, NEWS, README, dbflib.i,
+	dbflib.py, dbflib_wrap.c, pyshapelib_api.h, pytest.py, setup.py,
+	shapelib.i, shapelib.py, shapelib_wrap.c, shptreemodule.c: These files
+	have been moved here from thuban/extensions/pyshapelib/
+	See there in the Attic for the older history.
+
+	* libraries/shapelib/ dbfopen.c, shapefil.h, shpopen.c, shptree.c: These
+	files have been moved here from thuban/extensions/shapelib/
+	See there in the Attic for the older history.
+
+	* libraries/thuban/ bmpdataset.cpp, cpl_mfile.cpp, cpl_mfile.h,
+	gdalwarp.cpp, wxproj.cpp: These files have been moved here from
+	thuban/extensions/thuban/
+	See there in the Attic for the older history.
+
+	* MANIFEST.in, setup.cfg, setup.py: renamed extensions to libraries.
+
+	* extensions/thuban/ bmpdataset.cpp, cpl_mfile.cpp, cpl_mfile.h,
+	gdalwarp.cpp, wxproj.cpp: Moved to libraries/thuban.
+
+	* extensions/shapelib/ dbfopen.c, shapefil.h, shpopen.c, shptree.c:
+	Moved to libraries/shapelib.
+
+	* extensions/pyshapelib/ COPYING, NEWS, dbflib.py, pytest.py,
+	shapelib.py, README, dbflib_wrap.c, setup.py, shapelib_wrap.c,
+	ChangeLog, dbflib.i, pyshapelib_api.h, shapelib.i, shptreemodule.c:
+	Moved to libraries/pyshapelib.
+
+	* extensions/pyprojection/ MANIFEST.in, Projection.py, setup.py,
+	LICENSE, Projection.i, Projection_wrap.c, swighelp.txt:
+	Moved to libraries/pyprojection.
+
+	* extensions/ pyprojection, pyshapelib, shapelib, thuban: Removed.
+
+	* extensions: Removed.
+
+2003-08-19  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_viewport.py (ViewPortTest): We don't use the
+	facilities of FileTestMixin so don't derive from it.
+	(TestViewportWithPostGIS): New class with tests for using a
+	viewport on a map with postgis layers.
+
+2003-08-19  Bernhard Herzog  <bh at intevation.de>
+
+	Add the db connection management to the session.
+
+	* Thuban/Model/session.py (Session.__init__): New instance
+	variable db_connections
+	(Session.AddDBConnection, Session.DBConnections)
+	(Session.HasDBConnections, Session.CanRemoveDBConnection)
+	(Session.RemoveDBConnection): New methods to manage and query the
+	db connections managed by the session
+	(Session.OpenDBShapeStore): New method to open a shapestore from a
+	db connection
+
+	* Thuban/Model/messages.py (DBCONN_REMOVED, DBCONN_ADDED): New
+	messages for the db connection handling in the session
+
+	* test/test_postgis_session.py: New. test cases for the session's
+	db connection handling with postgis connections
+
+2003-08-19  Bernhard Herzog  <bh at intevation.de>
+
+	Add very basic postgis database support and the corresponding test
+	cases. The test cases require a PostgreSQL + postgis installation
+	but no existing database. The database will be created
+	automatically by the test cases
+
+	* test/README: Add note about skipped tests and the requirements
+	of the postgis tests.
+
+	* Thuban/Model/postgisdb.py: New. Basic postgis database support.
+
+	* test/test_postgis_db.py: New. Test cases for the postgis
+	support.
+
+	* Thuban/Model/wellknowntext.py: New. Parser for well-known-text
+	format
+
+	* test/test_wellknowntext.py: New. Test cases for the
+	wellknowntext parser
+
+	* test/postgissupport.py: New. Support module for tests involving
+	a postgis database.
+
+	* test/support.py (execute_as_testsuite): Shut down the postmaster
+	if it's still running after the tests
+
+	* Thuban/Model/data.py (RAW_WKT): New constant for raw data in
+	well known text format
+
+2003-08-19  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Examples/simple_extensions/hello_world.py: New. Raises a Hello World
+	message dialog.
+
+2003-08-18  Bernhard Herzog  <bh at intevation.de>
+
+	* test/support.py (ThubanTestResult.printErrors): Indent the
+	reason for the skips in the output to make it a bit more readable.
+	(execute_as_testsuite): New helper function to run a test suite
+	and print some more information.
+	(run_tests): Use execute_as_testsuite to run the tests
+
+	* test/runtests.py (main): Use execute_as_testsuite to run the
+	tests
+
+2003-08-18  Bernhard Herzog  <bh at intevation.de>
+
+	Fix some bugs in Thuban and the test suite that were uncovered by
+	changes introduced in Python 2.3:
+
+	* Thuban/Model/table.py (DBFTable.__init__): Make sure the
+	filename is an absolute name
+
+	* Thuban/Model/layer.py (RasterLayer.__init__): Make sure the
+	filename is an absolute name
+
+	* test/test_save.py (SaveSessionTest.testRasterLayer): Use a
+	unique filename to save to and use the correct relative filename
+	in the expected output.
+	(SaveSessionTest.test_dbf_table): Use the correct relative
+	filename in the expected output.
+
+	* test/test_layer.py (TestLayer.test_raster_layer): Update the
+	test to check whether the filename is absolute.
+
+2003-08-18  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/about.py (About.__init__): Added Silke Reimer.
+
+2003-08-15  Bernhard Herzog  <bh at intevation.de>
+
+	Change the way shapes are returned by a shape store. The
+	ShapesInRegion method returns an iterator over actual shape
+	objects instead of a list of shape ids.
+
+	* Thuban/Model/data.py (ShapefileShape.ShapeID): New. Return shape
+	id.
+	(ShapefileStore.ShapesInRegion): Return an iterator over the
+	shapes which yields shape objects instead of returning a list of
+	shape ids
+	(ShapefileStore.AllShapes): New. Return an iterator over all
+	shapes in the shape store
+	(DerivedShapeStore.AllShapes): New. Like in ShapefileStore
+
+	* Thuban/Model/layer.py (Layer.ShapesInRegion): Update
+	doc-string.
+
+	* Thuban/UI/baserenderer.py
+	(BaseRenderer.layer_ids, BaseRenderer.layer_shapes): Rename to
+	layer_shapes and make it return an iterator containg shapes
+	instead of a list of ids.
+	(BaseRenderer.draw_shape_layer): Update doc-string; Adapt to
+	layer_shapes() change
+
+	* Thuban/UI/renderer.py (ScreenRenderer.layer_ids)
+	(ScreenRenderer.layer_shapes): Rename as in BaseRenderer
+
+	* Thuban/UI/viewport.py (ViewPort._find_shape_in_layer): Adapt to
+	changes in the ShapesInRegion return value.
+	(ViewPort._get_hit_tester): Remove commented out code
+
+	* test/mockgeo.py (SimpleShapeStore.ShapesInRegion): Adapt to the
+	new return value.
+	(SimpleShapeStore.AllShapes): New. Implement this method too.
+
+	* test/test_layer.py (TestLayer.test_arc_layer)
+	(TestLayer.test_polygon_layer, TestLayer.test_point_layer)
+	(TestLayer.test_point_layer_with_projection)
+	(TestLayer.test_derived_store): Adapt to changes in the
+	ShapesInRegion return value.
+
+	* test/test_shapefilestore.py
+	(TestShapefileStoreArc.test_shapes_in_region)
+	(TestShapefileStorePolygon.test_shapes_in_region)
+	(TestShapefileStorePoint.test_shapes_in_region): Adapt to changes
+	in the ShapesInRegion return value.
+	(TestShapefileStorePoint.test_all_shapes)
+	(TestShapefileStoreArc.test_shape_shapeid): New tests for the new
+	methods
+
+	* test/test_derivedshapestore.py
+	(TestDerivedShapeStore.test_shapes_in_region): Adapt to changes in
+	the ShapesInRegion return value.
+	(TestDerivedShapeStore.test_all_shapes)
+	(TestDerivedShapeStore.test_shape_shapeid): New tests for the new
+	methods
+
+2003-08-15  Bernhard Herzog  <bh at intevation.de>
+
+	Make the renderers deal correctly with raw vs. python level
+	representation of shape geometries
+
+	* Thuban/UI/baserenderer.py (BaseRenderer.low_level_renderer):
+	Return a flag useraw in addition to the callable and the parameter
+	to indicate whether the callable can deal with the raw shape data
+	or uses the higher level python lists of coordinates. The callable
+	now should accept either the raw data or the return value of the
+	shape's Points() method.
+	(BaseRenderer.draw_shape_layer): Adapt to the low_level_renderer
+	change
+	(BaseRenderer.projected_points): Instead of the shape id use the
+	points list as parameter.
+	(BaseRenderer.draw_polygon_shape, BaseRenderer.draw_arc_shape)
+	(BaseRenderer.draw_point_shape): Adapt to projected_points()
+	change and accept the points list as parameter instead of the
+	shape id.
+
+	* Thuban/UI/renderer.py (MapRenderer.low_level_renderer): Return
+	the useraw flag as required by the BaseRenderer
+	(ScreenRenderer.draw_shape_layer): Adapt to low-level renderer
+	changes.
+
+	* test/test_baserenderer.py
+	(TestBaseRenderer.test_point_with_classification): New test for
+	rendering a map with classifications.
+
+2003-08-15  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/viewport.py (ViewPort.find_shape_at)
+	(ViewPort._find_shape_in_layer, ViewPort._find_shape_in_layer)
+	(ViewPort._get_hit_tester, ViewPort.projected_points)
+	(ViewPort._hit_point, ViewPort._hit_arc, ViewPort._hit_polygon)
+	(ViewPort._find_label_at): Split the find_shape_at method into
+	several new methods and use the functions in the hit-test module.
+
+	* Thuban/UI/hittest.py: New module with Python-level hit-testing
+	functions
+
+	* test/test_hittest.py: New. Test for the new hittest module
+
+2003-08-15  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.ShapesInRegion): Apply the layer
+	projection to all corners of the bounding box to get a better
+	approximation of the projected bounding box
+
+	* test/test_layer.py (TestLayer.test_point_layer_with_projection):
+	New. Test coordinate handling of a layer with a projection.
+	Catches the bug fixed in Layer.ShapesInRegion
+
+2003-08-15  Bernhard Herzog  <bh at intevation.de>
+
+	Move some of the mock objects in test_baserenderer into their own
+	module so they can easily be used from other tests
+
+	* test/mockgeo.py: New test helper module with some mock objects
+	for geometry related things like shapes, shapestores and
+	projections.
+
+	* test/test_mockgeo.py: New. Tests for the new helper module
+
+	* test/test_baserenderer.py: Some of the mock-objects are in
+	mockgeo now.
+
+2003-08-12  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/about.py (About.__init__): Added Björn Broscheit.
+
+2003-08-12  Bernhard Herzog  <bh at intevation.de>
+
+	* po/de.po: New. German translations by Bjoern Broscheit
+
+2003-08-12  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/projdialog.py (UnknownProjPanel._DoLayout): Translated
+	strings have to be one string literal.
+
+2003-08-11  Bernhard Herzog  <bh at intevation.de>
+
+	* test/support.py (FloatComparisonMixin.assertPointListEquals):
+	New. This method was used in various derived classes, but it's
+	better to have it here.
+
+	* test/test_shapefilestore.py
+	(ShapefileStoreTests.assertPointListEquals): Removed. It's now in
+	FloatComparisonMixin
+
+	* test/test_layer.py (TestLayer.assertPointListEquals): Removed.
+	It's now in FloatComparisonMixin
+
+	* test/test_derivedshapestore.py
+	(TestDerivedShapeStore.assertPointListEquals): Removed. It's now
+	in FloatComparisonMixin
+
+2003-08-11  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/join.py (JoinDialog.OnJoin): Add missing space to
+	error message
+
+2003-08-08  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Now use authorgroup. Added revhistory
+	with version number.
+	Changed title to reflect version number of Thuban.
+
+2003-08-08  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/about.py (About.__init__): Reworked the hall of fame. Now
+	the list corresponds to the "About" web page.
+
+2003-08-08  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/projdialog.py (UTMProposeZoneDialog.dialogLayout):
+	Make sure translated strings are recognized as one string literal.
+
+	* Thuban/UI/proj4dialog.py (UTMProposeZoneDialog.dialogLayout):
+	Make sure translated strings are recognized as one string literal.
+
+	* Thuban/UI/classgen.py (ClassGenDialog.OnOK): Make sure
+	translated strings are recognized as one string literal.
+
+	* Thuban/UI/application.py (ThubanApplication.OpenSession): Make
+	sure translated strings are recognized as one string literal.
+
+2003-08-07  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/data.py (DerivedShapeStore.RawShapeFormat): New.
+	Simply delegates to the original shapestore.
+
+	* test/test_derivedshapestore.py
+	(TestDerivedShapeStore.test_raw_format): New. Test case for
+	DerivedShapeStore.RawShapeFormat
+
+2003-08-07  Bernhard Herzog  <bh at intevation.de>
+
+	Add raw data interface to shape objects.
+
+	* Thuban/Model/data.py (ShapefileShape, Shape): Rname the shape
+	class to ShapefileShape which now holds shapefile specific
+	information.
+	(ShapefileShape.compute_bbox): Simplified to not cache any
+	information. The way this method is used that shouldn't matter
+	performance wise.
+	(ShapefileShape.RawData): New. Return the shapeid which is the raw
+	data format for shapes from shapefiles.
+	(ShapefileStore.RawShapeFormat): New. Return the raw datatype used
+	in the shape objects returned by a shapestore. For a
+	ShapefileStore this is always RAW_SHAPEFILE.
+	(RAW_PYTHON, RAW_SHAPEFILE): Constants for the RawShapeFormat
+	method.
+
+	* test/test_shapefilestore.py
+	(TestShapefileStore.test_raw_format): New test to test the raw
+	format feature of shapes.
+
+	* Thuban/Model/layer.py: Remove the unused import of Shape from
+	data. It was only there for interface compatibility but it's not
+	used inside of Thuban and the generic Shape class has gone away.
+
+	* Thuban/UI/renderer.py (MapRenderer.low_level_renderer): Check
+	the raw data format and only use an optimized version of its a
+	shapefile.
+
+2003-08-07  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_baserenderer.py (SimpleShape): Shape class for the
+	tests.
+	(SimpleShapeStore.Shape): Use SimpleShape instead of
+	Thuban.Model.data.Shape to make the tests independed of the coming
+	changes.
+
+2003-08-07  Bernhard Herzog  <bh at intevation.de>
+
+	* test/support.py (SkipTest, ThubanTestResult, ThubanTestRunner)
+	(ThubanTestProgram): New classes that extend the respective
+	classes from unittest. These new version support skipping tests
+	under certain expected conditions. In the Thuban test suite we
+	uses this for tests that require the optional gdal support.
+	(run_tests): Use ThubanTestProgram instead of the unittest.main()
+
+	* test/runtests.py (main): Use the new ThubanTestRunner instead of
+	the normal one from unittest
+
+	* test/test_layer.py (TestLayer.test_raster_layer): If this test
+	is not run because gdal support isn't available report this to the
+	runner.
+
+	* test/test_baserenderer.py
+	(TestBaseRenderer.test_raster_no_projection): Do not run this test
+	if gdal support isn't available and report this to the runner.
+
+2003-08-06  Bernhard Herzog  <bh at intevation.de>
+
+	Rearrange the renderers a bit, partly in preparation for changes
+	required for the postgis merge, partly to make it more testable.
+	Also make the representation of coordinates in Shapes more
+	consistent.
+
+	* Thuban/UI/renderer.py (MapRenderer): Most of the code/methods in
+	this class is now in BaseRenderer. This class is now practically
+	only a specialization of BaseRenderer for rendering to an actual
+	wx DC.
+	(ScreenRenderer.draw_shape_layer): Use self.low_level_renderer()
+	to get the shapetype specific rendering functions.
+
+	* Thuban/UI/baserenderer.py: New file with the basic rendering
+	logic. The code in this file is completely independend of wx.
+	(BaseRenderer): Class with the basic rendering logic
+
+	* test/test_baserenderer.py: New. Test cases for BaseRenderer
+
+	* Thuban/UI/view.py (MapCanvas.__init__): New instance variable
+	error_on_redraw to guard agains endless loops and stack overflows
+	when there's a bug in the rendering code that raises exceptions.
+	(MapCanvas.OnIdle, MapCanvas._do_redraw): Split the actual
+	rendering into a separate method _do_redraw so that error handling
+	is a bit easier. When an exception occurs, set error_on_redraw to
+	true. When it's true on entry to OnIdle do nothing and return
+	immediately.
+
+	* Thuban/Model/data.py (ShapefileStore.Shape): For consistency, a
+	Shape object will always have the coordinates as a list of list of
+	coordinate pairs (tuples).
+	(Shape.compute_bbox): Adapt to new representation.
+
+	* Thuban/UI/viewport.py (ViewPort.find_shape_at)
+	(ViewPort.LabelShapeAt): Adapt to new coordinate representation in
+	Shape objects.
+
+	* test/test_shapefilestore.py
+	(ShapefileStoreTests.assertFloatTuplesEqual)
+	(ShapefileStoreTests.assertPointListEquals): Rename to
+	assertPointListEquals and change purpose to checking equality of
+	the lists returned by Shape.Points().
+	(TestShapefileStoreArc.test_shape)
+	(TestShapefileStorePolygon.test_shape)
+	(TestShapefileStorePoint.test_shape): Use the new
+	assertPointListEquals instead of assertFloatTuplesEqual
+
+	* test/test_layer.py (TestLayer.assertFloatTuplesEqual)
+	(TestLayer.assertPointListEquals): Rename to assertPointListEquals
+	and change purpose to checking equality of the lists returned by
+	Shape.Points().
+	(TestLayer.test_arc_layer, TestLayer.test_arc_layer)
+	(TestLayer.test_polygon_layer, TestLayer.test_point_layer)
+	(TestLayer.test_derived_store): Use the new assertPointListEquals
+	instead of assertFloatTuplesEqual
+
+	* test/test_derivedshapestore.py
+	(TestDerivedShapeStore.assertFloatTuplesEqual)
+	(TestDerivedShapeStore.assertPointListEquals): Rename to
+	assertPointListEquals and change purpose to checking equality of
+	the lists returned by Shape.Points().
+	(TestDerivedShapeStore.test_shape): Use the new
+	assertPointListEquals instead of assertFloatTuplesEqual
+
+2003-08-06  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/projdialog.py (UTMPanel._OnPropose): Added test for
+	a bounding box. A dialog is raised in case, no bounding box
+	is found. This fixes bug #2043:
+	https://intevation.de/rt/webrt?serial_num=2043
+
+2003-08-05  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/color.py (Color.__repr__): Make the repr of a color
+	object look like a Color instantiation. Formerly it looked like a
+	tuple.
+
+	* test/test_color.py (TestColor.test_repr)
+	(TestColor.test_equality, TestColor.test_inequality): New. test
+	some more apects of the Color class
+	(TestTransparent.test_repr, TestTransparent.test_hex)
+	(TestTransparent.test_equality): New. Test cases for the
+	Transparent object.
+
+2003-08-04  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: a number of small improvements.
+	The resulting file is the version submitted for GREAT-ER II.
+
+2003-08-01  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/resource.py, Thuban/UI/projdialog.py,
+	Thuban/UI/join.py, Thuban/UI/classgen.py, Thuban/UI/about.py,
+	Thuban/Model/resource.py: Insert cvs keywords and doc-strings.
+
+	* Thuban/UI/common.py: Insert cvs keywords and doc-strings.
+	(Color2wxColour, wxColour2Color, ThubanBeginBusyCursor)
+	(ThubanEndBusyCursor): Add doc-strings
+
+2003-08-01  Bernhard Herzog  <bh at intevation.de>
+
+	First step towards PostGIS integration. More abstraction by movin
+	more code from the layer to the shapestore. More methods of the
+	layer are now simply delegated to the equivalent method of the
+	shapestore. The SHAPETYPE_* constants are now in data not in
+	layer.
+
+	* Thuban/Model/data.py (SHAPETYPE_POLYGON, SHAPETYPE_ARC)
+	(SHAPETYPE_POINT, Shape): Move these constants and classes from
+	layer.py to data.py
+	(ShapefileStore.__init__): More Initialization for the new methods
+	and functionality.
+	(ShapefileStore.ShapeType, ShapefileStore.NumShapes)
+	(ShapefileStore.BoundingBox, ShapefileStore.ShapesInRegion)
+	(ShapefileStore.Shape): New methods that were formerly implemented
+	in the layer.
+	(DerivedShapeStore.Shape, DerivedShapeStore.ShapesInRegion)
+	(DerivedShapeStore.ShapeType, DerivedShapeStore.NumShapes)
+	(DerivedShapeStore.BoundingBox): New. DerivedShapeStore
+	equivalents of the new shape methods. These versions are simply
+	delegated to the original shapstore.
+
+	* Thuban/Model/layer.py (SHAPETYPE_POLYGON, SHAPETYPE_ARC)
+	(SHAPETYPE_POINT, Shape): Removed. They're now in data.py
+	(Layer.SetShapeStore): Removed the initializatin of instance
+	variables that were needed for the stuff that's now in
+	ShapefileStore
+	(Layer.BoundingBox, Layer.NumShapes, Layer.ShapeType)
+	(Layer.Shape, Layer.ShapesInRegion): Simply delegate to the
+	shapestore.
+
+	* Thuban/UI/classifier.py, Thuban/UI/renderer.py,
+	Thuban/UI/viewport.py: Import the SHAPETYPE_* constants from data
+	instead of layer.
+
+	* test/test_shapefilestore.py: New. Tests for ShapefileStore.
+
+	* test/test_derivedshapestore.py: New. Tests for DerivedShapeStore.
+
+	* test/test_layer.py: Import the SHAPETYPE_* constants from data
+	instead of layer.
+	(TestLayer.test_derived_store): Remove the test for the exception
+	when instantiating the DerivedShapeStore with an incompatible
+	table which is now in test_derivedshapestore.py. Add some more
+	tests of the layer methods to determine whether they work for a
+	DerivedShapeStore as well.
+
+2003-07-31  Jonathan Coles   <jonathan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Fix the list of required packages
+	by just listing the name and where they can be found.
+
+2003-07-31  Frank Koormann   <frank.koormann at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: 
+	Changed the screenshot elements to figure.
+	Changed some variablelist elements to itemizedlist.
+	Added section on GDAL formats.
+
+2003-07-31  Jonathan Coles   <jonathan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Added a few sentences about
+	the Fix Border Color option when generating classes.
+
+2003-07-30  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classgen.py: Add docstrings. Rename specific
+	Ramp instances to use lower_case_style.
+
+	* Thuban/UI/classgen.py: Use renamed Ramp instances.
+	
+	* Thuban/UI/classifier.py: Add docstrings.
+
+	* Thuban/UI/dock.py: Add docstrings.
+
+	* test/test_classgen.py: Use renamed Ramp instances.
+
+2003-07-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Lib/connector.py (QueueingPublisher): Removed. This class
+	was never used in Thuban.
+
+2003-07-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/join.py (JoinDialog.__init__): Use the table's Title()
+	method directly instead of going through the transient_table
+	method. This faster because transient_table may force the copy of
+	a DBF file into the transient database and setting a table's title
+	doesnm't affect the title of the associated transient table, so
+	this fixes RT #2042
+
+	* Thuban/UI/main.py (__version__): Don't import the already
+	removed show_exception_dialog.
+
+2003-07-29  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/application.py (ThubanApplication.ShowExceptionDialog):
+	Put back this method and remove the equivalent function since we
+	are setting the exception hook from within this class (OnInit).
+
+2003-07-29  Jonathan Coles   <jonathan at intevation.de>
+
+	* Doc/manual/images/5_2_custom_ramp.png,
+	Doc/manual/images/5_2_quantiles.png,
+	Doc/manual/images/5_2_uniform_dist.png,
+	Doc/manual/images/5_2_unique_values.png,
+	Doc/manual/images/8_int_error.png: New screen shots.
+
+	* Doc/manual/thuban-manual.xml: Fixed typos and wording, clarified
+	some points, and added more screen shots.
+
+2003-07-29  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/data.py: Remove the now unused import of warnings
+
+2003-07-29  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/data.py (SimpleStore): Removed. This class has been
+	deprecated since before the 0.8 release and isn't used in Thuban
+	itself anymore.
+
+	* Thuban/Model/transientdb.py: Remove some unnecessary imports
+
+2003-07-29  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/application.py (ThubanApplication.OnInit): set the 
+	python exception hook here so that we are sure to catch any
+	Thuban exception that happen during initialization.
+
+	* Thuban/UI/main.py (main): Don't set the exception hook here,
+	it will get set in ThubanApplication.OnInit.
+
+2003-07-29  Jonathan Coles   <jonathan at intevation.de>
+                                                                            
+	* Thuban/UI/application.py (ThubanApplication.ShowExceptionDialog):
+	Removed and called it show_exception_dialog() so that the exception
+	handler can be set before the class is created.
+                                                                            
+	* Thuban/UI/main.py (main): Install the exception handler before
+	a ThubanApplication is created.
+                                                                                
+2003-07-29  Bernhard Herzog  <bh at intevation.de>
+
+	* po/it.po: New. Italian translation by Maurizio Napolitano
+
+	* po/ru.po: New. Russian translation by Alex Shevlakov
+
+2003-07-29  Frank Koormann   <frank.koormann at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Extended section on supported
+	projections.
+	
+2003-07-29  Frank Koormann   <frank.koormann at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: gaspell-checked.
+
+2003-07-29  Jonathan Coles   <jonathan at intevation.de>
+
+	* Doc/manual/images/3_5_legend.png: Added border to improve look
+	on white background.
+
+2003-07-29  Jonathan Coles   <jonathan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Fixed grammar and typos. Added 
+	descriptions for the legend toolbar.
+
+	* Doc/manual/images/4_2_raster_layer_properties.png: Removed
+	cursor from dialog box.
+
+2003-07-28  Jonathan Coles   <jonathan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: More screenshots and more chapters.
+
+	* Doc/manual/images/2_4_session_tree.png, 
+	Doc/manual/images/3_5_legend.png, Doc/manual/images/3_rename_map.png,
+	Doc/manual/images/4_2_layer_properties.png, 
+	Doc/manual/images/4_2_raster_layer_properties.png,
+	Doc/manual/images/5_3_genclass.png, 
+	Doc/manual/images/5_classification.png, 
+	Doc/manual/images/6_projection.png,
+	Doc/manual/images/7_1_table_view.png, 
+	Doc/manual/images/7_2_5_join.png: New screenshots.
+
+2003-07-24  Jonathan Coles   <jonathan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Chapter on Projection Management.
+
+2003-07-24  Jonathan Coles   <jonathan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Added EPS images and wrote
+	chapter on Layer Management.
+
+	* Doc/manual/Makefile: New. Makefile to generate all formats for the
+	manual and images.
+
+2003-07-24  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/range.py, Thuban/version.py: Remove the #! line as
+	it annoys lintian which warns about these files not being
+	executable. The #! isn't necessary here since if you absolutely
+	must execute them you can always say "python <filename>".
+
+	* Thuban/UI/renderer.py (ScreenRenderer.draw_shape_layer): Remove
+	superfluous code to set brush and pen for point shapes
+
+	* Thuban/UI/viewport.py: Remove commented out code that wouldn't
+	belong in viewport anyway
+
+2003-07-24  Frank Koormann   <frank.koormann at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Added section on table management.
+
+2003-07-24  Bernhard Herzog  <bh at intevation.de>
+
+	* test/runtests.py (main): Recognize the long "verbose" option
+	correctly.
+
+2003-07-22  Jonathan Coles   <jonathan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Continue to write first revision
+	of the manual.
+
+	* Thuban/UI/renderer.py (MapRenderer.render_map): Wrap method
+	with Begin/EndDrawing() calls to ensure we aren't doing to
+	many updates to the dc during rendering.
+	(ScreenRenderer.draw_shape_layer): self.draw_point_shape takes
+	a pen and brush argument so they need to be passed to the function.
+
+	* Thuban/UI/viewport.py (ViewPort.calc_min_max_scales): New.
+	Calculates the minimum and maximum scale values. Factored out
+	of set_view_transform so that it could be used to zoom all the
+	way into a single point.
+	(ViewPort.set_view_transform): Call calc_min_max_scales().
+	(ViewPort.FitSelectedToWindow): Zoom to the maximum scale
+	if only a single point is selected.
+
+	* Doc/manual/images/1_2_legend_close.png,
+	Doc/manual/images/1_2_legend_dock.png,
+	Doc/manual/images/1_2_mainwindow.png,
+	Doc/manual/images/1_2_mainwindow.ps,
+	Doc/manual/images/1_2_mainwindow.sk,
+	Doc/manual/images/3_2_fullextent.png,
+	Doc/manual/images/3_2_fulllayerextent.png,
+	Doc/manual/images/3_2_fullshapeextent.png,
+	Doc/manual/images/3_2_pan.png,
+	Doc/manual/images/3_2_zoomin.png,
+	Doc/manual/images/3_2_zoomout.png,
+	Doc/manual/images/3_3_identify.png,
+	Doc/manual/images/3_3_label.png,
+	Doc/manual/images/3_5_invisible.png,
+	Doc/manual/images/3_5_movedown.png,
+	Doc/manual/images/3_5_moveup.png,
+	Doc/manual/images/3_5_props.png,
+	Doc/manual/images/3_5_tobottom.png,
+	Doc/manual/images/3_5_totop.png,
+	Doc/manual/images/3_5_visible.png: New. Images for the documentation.
+
+2003-07-18  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/messages.py (MAP_REPLACED): New message.
+
+	* Thuban/UI/viewport.py (ViewPort.SetMap): Issue MAP_REPLACED
+	after the new map has been assigned
+
+	* Thuban/UI/mainwindow.py (MainWindow.delegated_messages):
+	Delegate MAP_REPLACED to the canvas too
+	(MainWindow.prepare_new_session): Removed. Thanks to the new
+	MAP_REPLACED message it's no longer needed
+	(MainWindow.OpenSession, MainWindow.NewSession):
+	prepare_new_session has been removed.
+
+	* Thuban/UI/classifier.py (Classifier.__init__): Subscribe to
+	MAP_REPLACED so that we can close the dialog if a new map is set.
+	(Classifier.unsubscribe_messages): Unsubscribe from MAP_REPLACED
+	(Classifier.map_replaced): Handle MAP_REPLACED by closing the
+	dialog
+
+	* test/test_viewport.py (SimpleViewPortTest)
+	(SimpleViewPortTest.test_default_size): Add doc-strings
+	(ViewPortTest.setUp): Bind map to self.map so we can use it in
+	tests. Subscribe to MAP_REPLACED messages too.
+	(ViewPortTest.tearDown): No need to explicitly unsubscribe
+	(ViewPortTest.test_set_map): New test for the SetMap method.
+
+2003-07-18  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_viewport.py (SimpleViewPortTest.test_default_size):
+	Move this test from ViewPortTest.setUp to this new separate test
+	case. setUp is not the place for the actual tests.
+	(ViewPortTest.test_inital_settings, ViewPortTest.setUp): Move some
+	more of the test from setUp to the new test test_inital_settings.
+	(ViewPortTest.test_win_to_proj, ViewPortTest.test_proj_to_win)
+	(ViewPortTest.test_proj_conv): Split test_proj_conv into
+	test_win_to_proj and test_proj_to_win and make the tests easier to
+	understand
+	(ViewPortTest.testFitRectToWindow, ViewPortTest.testZoomFactor)
+	(ViewPortTest.testZoomOutToRect, ViewPortTest.testTranslate)
+	(ViewPortTest.test_unprojected_rect_around_point)
+	(ViewPortTest.test_find_shape_at, ViewPortTest.testTools):
+	Reformat to increase readability.
+
+2003-07-18  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py (MapCanvas.OnLeftDown): Capture the mouse.
+
+2003-07-18  Bernhard Herzog  <bh at intevation.de>
+
+	* test/runtests.py: The test suite can now be run without an X
+	connection. To make sure this remains true, remove the DISPLAY
+	environment variable so that an error occurs if the wxGTK is
+	imported accidentally
+
+2003-07-18  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/viewport.py: Remove unused imports
+
+	* Thuban/UI/view.py: Remove unused imports
+
+2003-07-18  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_export.py Remove unused imports. The OutputTransform
+	function is now in viewport.py and is called output_transform
+	(TestScalebar.test_output_transform)
+	(TestScalebar.test_OutputTransform): Renamed to
+	test_output_transform and updated to use output_transform instead
+	of OutputTransform
+
+	* Thuban/UI/view.py (OutputTransform): Moved to viewport.py and
+	renamed.
+	(MapCanvas.Export, MapPrintout.draw_on_dc): OutputTransform was
+	renamed to output_transform
+
+	* Thuban/UI/viewport.py (OutputTransform, output_transform):
+	Rename to output_transform
+
+2003-07-18  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.__init__): Rename
+	classificationField to classificatin_column and init it here so
+	that it can be used in SetClassificationColumn
+	(Layer.GetClassificationColumn, Layer.GetClassificationField):
+	Rename to GetClassificationColumn.
+	(Layer.SetClassificationColumn, Layer.SetClassificationField):
+	Rename to SetClassificationColumn and issue a LAYER_CHANGED
+	message if the column changes.
+	(Layer._classification_changed, Layer.ClassChanged): Rename to
+	_classification_changed. Update the callers.
+	(Layer.SetShapeStore): Further field->column renames.
+
+	* Thuban/Model/load.py (SessionLoader.start_classification) 
+	(SessionLoader.start_clpoint): Updates because of
+	field->column method name changes in the Layer class
+
+	* Thuban/Model/save.py (SessionSaver.write_classification): Updates
+	because of field->column method name changes in the Layer class
+
+	* Thuban/UI/classifier.py (Classifier.__init__)
+	(Classifier._OnTry, Classifier._OnRevert): Updates because of
+	field->column method name changes in the Layer class
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Updates
+	because of field->column method name changes in the Layer class
+
+	* Thuban/UI/viewport.py (ViewPort.find_shape_at): Updates because
+	of field->column method name changes in the Layer class
+
+	* test/test_save.py (SaveSessionTest.testClassifiedLayer)
+	(SaveSessionTest.testClassifiedLayer): Update because of
+	field->column method name changes in the Layer class
+
+	* test/test_layer.py (SetShapeStoreTests.setUp)
+	(SetShapeStoreTests.test_sanity): Update because of field->column
+	method name changes in the Layer class
+	(TestLayerModification.setUp): Subscribe to LAYER_CHANGED as well
+	(TestLayerModification.test_sanity)
+	(TestLayerModification.test_initial_settings): remove unsued code
+	and rename to test_sanity.
+	(TestLayerModification.test_set_classification): New test for
+	SetClassification and SetClassificationField.
+
+2003-07-18  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_classgen.py (TestFixedRamp.test): Extend test to check
+	the non-fixed values as well. The old test would have accepted a
+	fixed ramp that only returnes the fixed properties
+
+2003-07-17  Jonathan Coles   <jonathan at intevation.de>
+
+	* Doc/manual/mainwindow.png, Doc/manual/mainwindow.xcf: Screen
+	shots for the manual. The XCF file is the source image and
+	has additional layers to support changes.
+
+	* Doc/manual/thuban-manual.xml: Wrote an initial Introduction.
+
+	* Thuban/UI/classifier.py (Classifier.__BuildClassification):
+	Return both the new class and the field name.
+
+	* Thuban/UI/mainwindow.py (MainWindow.ToggleLegend): Don't 
+	fit the map to the window as this changes any zoom level that
+	the user may have set.
+
+2003-07-16  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classgen.py (generate_singletons,
+	generate_uniform_distribution, generate_quantiles): Remove
+	fixes parameter, but maintain the same functionality by having
+	the calling function pass a FixedRamp object for the ramp.
+	(FixedRamp): New. Adapts a ramp to have fixed property values.
+
+	* Thuban/Model/classification.py: Use new CLASS_CHANGED message.
+	(Classification): Inherit from Publisher.
+	(Classification.__init__): Remove the layer parameter. 
+	Classifications no longer need to have a parent layer.
+	(Classification.GetField, Classification.GetFieldType, 
+	Classification.SetFieldInfo): Removed. The field name is stored
+	in the layer, and the type can be retreived by calling
+	Layer.GetFieldType().
+	(Classification._set_layer, Classification.GetLayer): Removed.
+	Classifications no longer have a parent layer.
+
+	* Thuban/Model/layer.py (Layer.Destroy): Unsubscribe from the
+	classification. 
+	(Layer.SetShapeStore): Reset the classification first while
+	we still have the old shape store to work with.
+	(Layer.GetClassificationField, Layer.SetClassificationField):
+	New. Method for getting/setting the field to classify on.
+	(Layer.SetClassification): Simplified now that the layer 
+	simply has to hold a reference to the classification and not
+	tell the classification who owns it.
+	Fixes RTbug #2023.
+
+	* Thuban/Model/load.py (SessionLoader.start_classification):
+	Set the field name on the layer, not the classification.
+
+	* Thuban/Model/messages.py: Add CLASS_CHANGED for when a
+	classification is modified.
+
+	* Thuban/Model/save.py (SessionSaver.write_classification):
+	Get the field name and type from the layer.
+
+	* Thuban/Model/table.py (table_to_dbf, table_to_csv): Renamed
+	parameter records to rows and add docstring. Fixes RTbug #1997.
+
+	* Thuban/UI/classgen.py (ClassGenDialog.OnOK): Use a fixed
+	ramp when we need to fix certain values of a ramp rather than
+	using the old fixes parameter. Fixes RTbug #2024.
+
+	* Thuban/UI/classifier.py (ClassGrid.CreateTable): Add fieldType
+	parameter.
+	(ClassTable.Reset): Add fieldType parameter and use it, rather
+	than asking the classification.
+	(Classifier.__init__): Remember the original class's field
+	and ask the layer for the field type, rather than the classification.
+	(Classifier.__SetGridTable): Retrieve the field and field type
+	for the table because they are not in the classification.
+	(Classifier._OnTry, Classifier._OnRevert): Set the classification
+	field on the layer in addition to the classification itself.
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Get the
+	classification field from layer.
+
+	* Thuban/UI/viewport.py (ViewPort.find_shape_at): Get the
+        classification field from layer. Split up tests and remove
+	*-imports. Fixes RTbug #1992.
+
+	* test/test_classgen.py (TestFixedRamp): Test for the FixedRamp class.
+
+	* test/test_classification.py
+	(TestClassification.test_classification): Remove tests for methods
+	that no longer exist.
+
+	* test/test_layer.py (SetShapeStoreTests.setUp): Classification
+	__init__ no longer has a field parameter, use SetClassificationField.
+	(SetShapeStoreTests.test_sanity): Use layer object to get class
+	field info.
+
+	* test/test_save.py (SaveSessionTest.testClassifiedLayer): Use
+	SetClassificationField on layer to set class field info.
+
+	* test/test_viewport.py: Renamed from test/test_view.py.
+
+2003-07-16  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Added authors and an initial
+	coarse structure.
+
+2003-07-15  Bernhard Herzog  <bh at intevation.de>
+
+	* test/support.py (FloatComparisonMixin): This is a mix-in class
+	and therefore should not be derived from any other class.
+
+	* test/test_range.py (RangeTest): FloatComparisonMixin is a
+	mix-in, so derive from TestCase as well.
+
+2003-07-15  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Rework the
+	draw_func handling a bit to remove one layer of indirection. This
+	makes the renderer about 10% faster in the non-classifying case
+	and the code a bit cleaner
+	(MapRenderer.draw_point_shape): Add the pen and brush parameters
+	and set them in the dc. Now the draw_point_shape method and
+	wxproj's draw_polygon_shape function have basically the same
+	signature so that both can be directly used as draw_func
+
+2003-07-15  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/save.py (SessionSaver.write_classification): Encode
+	string values (in addition to the labels) as UTF 8
+
+	* Thuban/Model/load.py (SessionLoader.start_clpoint): Decode the
+	values if the field type is string
+
+	* test/test_save.py (SaveSessionTest.testClassifiedLayer): Test
+	saving a session with non-ascii string classification values.
+
+	* test/test_load.py (TestClassification.file_contents)
+	(TestClassification.test): Check for non-ascii values in string
+	classifications
+
+2003-07-14  Jonathan Coles   <jonathan at intevation.de>
+
+	* test/test_view.py: New. Tests for ViewPort.
+
+2003-07-14  Frank Koormann   <frank at intevation.de>
+
+	* Thuban/Model/load.py (SessionLoader.start_map): Encode map 
+	title to latin1.  Fixes https://intevation.de/rt/webrt?serial_num=2013
+
+	* test/test_load_0_8.py (TestUnicodeStrings): New, test load of 
+	unicode strings from session file: session title, map title and 
+	projection name.
+	
+2003-07-10  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/viewport.py (Tool.MouseUp): Should have called
+	drag_stop, not drag_move when the mouse is released.
+
+2003-07-10  Jonathan Coles   <jonathan at intevation.de>
+
+	The most important part of this is the seperation of view.py into
+	two pieces. viewport.py now has a class called ViewPort which
+	contains all the non-wx parts of view.py and can therefore be
+	tested. view.py contains only the wx-specific parts and is fairly
+	simple.
+
+	* Thuban/UI/view.py: Stripped out all non-wx functionality. Fixes
+	RTTbug #1992.
+	* Thuban/UI/viewport.py: New. Contains non-wx view functionality.
+	RTTbug #1992.
+
+	* Thuban/Model/classgen.py (generate_singletons,
+	generate_uniform_distribution, generate_quantiles):
+	Added 'fixes' parameter so that property attributes can
+	be held constant over the generated classification groups.
+	(CustomRamp.GetProperties): Remove unused variables.
+
+	* Thuban/Model/map.py (Map.SetProjection): Send the old
+	projection as an argument to listeners of the MAP_PROJECTION_CHANGED
+	event.
+
+	* Thuban/Model/table.py (table_to_dbf, table_to_csv): Added 'records' 
+	parameter which is a list of records that restricts which
+	records are saved. Fixes RTbug #1997.
+
+	* Thuban/UI/application.py (ThubanApplication.ShowExceptionDialog):
+	Port exception dialog from GREAT-ER. Fixes RTbug #1993.
+
+	* Thuban/UI/classgen.py (ClassGenDialog.__init__): Add controls
+	to allow the user to fix line color/width on generated groups.
+	(ClassGenDialog.OnOK): Use new 'fixes' parameter of the generate_*
+	functions to optionally fix group properties.
+
+	* Thuban/UI/main.py (main): Set exception hook to the 
+	ShowExceptionDialog. Fixes RTbug #1993.
+
+	* Thuban/UI/mainwindow.py (MainWindow.ShowTableView): Raise
+	the table window when it is selectd to be shown.
+
+	* Thuban/UI/tableview.py (QueryTableFrame.__init__): Add an
+	Export Selection button and move the export buttons underneath
+	the table.
+	(QueryTableFrame.UpdateStatusText): Added event argument so
+	that it can respond to grid selection events. The status text
+	is now updated even when the table is not associated with a
+	layer as was previously assumed.
+	(QueryTableFrame.OnGridSelectRange, OnGridSelectCell): Removed.
+	UpdateStatusText responds to these events.
+	(QueryTableFrame.OnSaveAs): Renamed to doExport.
+	(QueryTableFrame.doExport): Helper function that saves the
+	entire table, or selected rows, to a file.
+	(QueryTableFrame.OnExport, QueryTableFrame.OnExportSel): New.
+	Respond to export button events and call doExport.
+
+	* extensions/thuban/gdalwarp.cpp (ProjectRasterFile): Make sure
+	the function doesn't return NULL without first setting a Python
+	Error.
+
+	* test/runtests.py (main): Only print "Unknown option" for
+	unsupported options.
+
+	* test/support.py (FloatComparisonMixin.assertFloatEqual): Take
+	optional epsilon argument to specify floating point accuracy.
+	(FloatComparisonMixin.assertFloatSeqEqual): Call assertFloatEqual
+	for each item test.
+
+	* test/test_csv_table.py (TestCSVTable.test_table_to_cvs): Add
+	tests for saving selected records.
+
+	* test/test_dbf_table.py (TestTableToDBF.test_table_to_dbf): Add
+        tests for saving selected records.
+
+	* test/test_map.py (TestMapWithContents.test_set_projection):
+	MAP_PROJECTION_CHANGED events send the old projection.
+
+	* test/test_session.py 
+	(TestSessionWithContent.test_forward_map_projection): 
+	MAP_PROJECTION_CHANGED events send the old projection.
+
+	* test/test_table.py (TableTest): Update tests to use non-deprecated
+	functions.
+
+2003-07-08  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/transientdb.py (TransientTableBase.Width): The type
+	constants in the column objects are the standard ones defined in
+	the table module.
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_transienttable_to_dbf): New. Test whether
+	exporting transient tables as DBF works. This should catch the bug
+	just fixed in TransientTableBase.Width.
+
+2003-07-08  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/classgen.py (CustomRamp.GetProperties): Compute the
+	interpolated colors correctly.
+
+	* test/test_classgen.py (TestCustomRamp.test_color_interpolation):
+	New. Test case for the fix in classgen.py
+
+2003-07-08  Bernhard Herzog  <bh at intevation.de>
+
+	* test/runtests.py (main): Make the default output less verbose
+	and add a verbosity option (-v) to get the old output
+
+2003-07-08  Bernhard Herzog  <bh at intevation.de>
+
+	* Resources/XML/thuban-0.9.dtd: New. This will become the DTD for
+	0.9.
+
+	* Thuban/Model/transientdb.py (TransientJoinedTable.JoinType):
+	New. Return the join type
+
+	* Thuban/Model/save.py (SessionSaver.write_session): Use new 0.9
+	DTD
+	(SessionSaver.write_data_containers): Save the join type for
+	joined tables
+
+	* Thuban/Model/load.py (SessionLoader.__init__): Add the new 0.9
+	namespace
+	(SessionLoader.start_jointable): Handle the jointype attribute
+
+	* test/test_load_0_8.py: New. Effectively a copy of test_load.py
+	as of Thuban 0.8. These are now tests to determine whether Thuban
+	can still read files generated by Thuban 0.8
+
+	* test/test_load.py (LoadSessionTest.dtd)
+	(TestSingleLayer.file_contents)
+	(TestLayerVisibility.file_contents, TestLabels.file_contents)
+	(TestLayerProjection.file_contents)
+	(TestRasterLayer.file_contents, TestJoinedTable.file_contents)
+	(TestJoinedTable.file_contents)
+	(TestLoadError.file_contents): Update for new DTD
+	(TestJoinedTable.file_contents, TestJoinedTable.setUp): Add test
+	for new join type attribute
+
+	* test/test_save.py (SaveSessionTest.dtd)
+	(SaveSessionTest.testEmptySession)
+	(SaveSessionTest.testSingleLayer)
+	(SaveSessionTest.testLayerProjection)
+	(SaveSessionTest.testRasterLayer)
+	(SaveSessionTest.testClassifiedLayer)
+	(SaveSessionTest.test_dbf_table)
+	(SaveSessionTest.test_joined_table): Update for new DTD
+	(SaveSessionTest.test_joined_table): Add test for new join type
+	attribute
+
+2003-07-04  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/table.py (_find_dbf_column_names): New. Helper
+	function for table_to_dbf
+	(table_to_dbf): Deal with names longer than the 10 character limit
+
+	* test/test_dbf_table.py (TestTableToDBF.test_table_to_dbf): Add
+	doc-string
+	(TestTableToDBF.test_table_to_dbf_long_col_names): New test for
+	long column names
+
+2003-07-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Doc/manual/thuban-manual.xml: Fix the CVS Revision Tag syntax
+
+2003-07-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Doc/manual/thuban-manual.xml, Doc/manual/README: New. Skeleton
+	for the Thuban manual and README with some basic information about
+	the manual
+
+2003-07-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/transientdb.py (TransientJoinedTable.__init__):
+	Update doc-string
+	(TransientJoinedTable.create): Do not modify the column objects of
+	the input tables in place and copy all columns of the input tables
+	into the joined table after all.
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_transient_joined_table_same_column_name):
+	Update to reflect the new behavior
+	(TestTransientTable.test_transient_joined_table_with_equal_column_names):
+	Update to reflect the new behavior
+	(TestTransientTable.test_transient_joined_table_name_collisions_dont_modify_in_place):
+	New test case for a bug which modified the column objects in place
+
+2003-07-02  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classgen.py (generate_singletons, 
+	generate_uniform_distribution, generate_quantiles,
+	GenQuantiles0): Make sure maxValue isn't less than
+	one, otherwise we could divide by zero.
+
+	* test/test_classgen.py (ClassGenTest.doClassRangeTest,
+	ClassGenTest.doClassSingleTest): Call doBoundsTest to
+	check the end classification groups against the
+	proper property values.
+	(ClassGenTest.doBoundsTest): New. Checks the first and
+	last classification groups to make sure their properties 
+	are the correct upper and lower bounds for a color ramp.
+
+2003-07-02  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classgen.py (generate_singletons, 
+	generate_uniform_distribution, generate_quantiles,
+	GenQuantiles0): The denominator was one to high when
+	calculating the index for the ramp causing the index
+	to never to reach one.
+
+2003-07-02  Jonathan Coles   <jonathan at intevation.de>
+
+	Changed the singature of ClassGroupRange.__init__ and
+	ClassGroupRange.SetRange() so that the min/max values are
+	passed as a tuple. This makes a better calling scheme for
+	when a Range object is passed instead.
+
+	* Thuban/Model/classgen.py: Fixed parameters to 
+	ClassGroupRange constructor.
+
+	* Thuban/Model/classification.py (ClassGroupRange.__init__):
+	Consolidate the min/max parameters into a single _range which
+	can either be a tuple or a Range object.
+	(ClassGroupRange.SetRange): Consolidate the min/max parameters 
+	into a single _range which can either be a tuple or a Range object.
+
+	* Thuban/Model/load.py (SessionLoader.start_clrange): Fix
+	call to ClassGroupRange constructor to use a tuple.
+
+	* Thuban/Model/layer.py (Layer.SetClassification): Switch
+	the classification instance variable to the new class 
+	before calling _set_layer otherwise subscribers to a 
+	LAYER_CHANGED event will not see any difference.
+
+	* test/test_classification.py: Fix tests of ClassGroupRange
+	so that they use the new signature.
+
+	* test/test_load.py: Fix use of ClassGroupRange so that it 
+	uses the new signature.
+
+	* test/test_load_0_2.py: Fix use of ClassGroupRange so that it 
+	uses the new signature.
+
+	* test/test_save.py: Fix use of ClassGroupRange so that it 
+	uses the new signature.
+
+
+2003-07-01  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classgen.py: Fixes RTbug #1972, 1971.
+	Import used objects/class from color.
+	(generate_singletons): We don't
+	need the numGroups parameter anymore because we are using
+	the new ramps with GetProperties().
+	(generate_uniform_distribution): Use new ramp method
+	GetProperties().
+	(generate_quantiles, GenQuantiles0): Use new ramp method 
+	GetProperties().
+	(CustomRamp.SetNumGroups): Removed. The ramps now map
+	a value from 0 to 1 to class properties so the number
+	of groups is not needed ahead of time.
+	(CustomRamp.next): Removed. CustomRamp does not support
+	interation anymore.
+	(CustomRamp.GetProperties): Returns a ClassGroupProperties
+	object based on the index value from 0 to 1 that is
+	passed to it.
+	(GreyRamp, RedRamp, GreenRamp, BlueRamp, GreenToRedRamp):
+	Made into instances of Monochromatic class instread of
+	deriving from it.
+	(HotToCold.SetNumGroups): Removed. See CustomRamp.
+	(HotToCold.next): Removed. See CustomRamp.
+
+	* Thuban/Model/classification.py: Fixes RTbug #1973, 1971.
+	(Classification.SetField, Classification.SetFieldType): 
+	Replaced with SetFieldInfo.
+	(Classification.SetFieldInfo): New. Does a better job of
+	what SetField and SetFieldType used to do by combining
+	their function since they should really always be done
+	at the same time.
+	(Classification.SetLayer): Renamed to _set_layer.
+	(Classification._set_layer): Should only be called from
+	Layer's SetClassification. This does not cause a recursive 
+	call as SetLayer did because we know that Layer knows about
+	the classification.
+
+	* Thuban/Model/color.py: Fixes RTbug #1971.
+	(_Transparent): Renamed from Transparent so it doesn't
+	conflict with the module variable.
+	(Transparent, Black): Renamed from Color.Transparent, 
+	Color.Black so they are not class variables.
+
+	* Thuban/Model/layer.py: Fixes RTbug #1971, 1973.
+	(Layer.Destroy): We don't need to call SetClassification
+	anymore to clear out the back reference in the classifcation
+	to the layer. It's better to set it to None using _set_layer,
+	and we won't be creating another clas object too.
+	(Layer.SetClassification): Classification._set_layer is not
+	recursive so remove all the locking variables. Also clean
+	up the code so that it remains unchanged if something fails.
+
+	* Thuban/Model/load.py: Fixes RTbug #1971.
+	(SessionLoader.start_classification): Call 
+	Classification.SetFieldInfo().
+
+	* Thuban/Model/save.py: Removed import of Color which wasn't
+	being used.
+
+	* Thuban/UI/classgen.py: Fixes RTbug #1972.
+	(ClassGenDialog.__init__): Color ramps are now instances 
+	already so we don't need to create any new objects.
+	(ClassGenDialog.OnOK): Check for numGroups is no longer 
+	necessary because we never use it.
+
+	* Thuban/UI/classifier.py: Fixes RTbug #1971.
+	(Classifier.__BuildClassification, Classifier.__SetGridTable):
+	Call Classification.SetFieldInfo() instead of SetFieldType.
+
+	* Thuban/UI/renderer.py: Fixes RTbug #1971.
+
+	* Thuban/UI/view.py: Fixes RTbug #1974, 1971.
+	(MapCanvas.__init__): Subscribe to the idle time event. Set
+	background color to white.
+	(MapCanvas.OnPaint): Set a flag indicating that we should
+	render the map during idle time. If we already have a bitmap
+	just draw it now.
+	(MapCanvas.OnIdle): New. Render the map only during idle time.
+	This also fixes a problem with the busy cursor under gtk.
+
+	* test/test_classgen.py (ClassGenTest.test_generate_singletons):
+	Fix calls to generate_singletons because the signature changed.
+
+	* test/test_classification.py: Fix color references and
+	change calls to Classification.[SetField|SetFieldType] to
+	SetFieldInfo.
+
+	* test/test_load.py: Fix color references.
+
+	* test/test_load_0_2.py: Fix color references.
+
+	* test/test_save.py (SaveSessionTest.testClassifiedLayer):
+	Change calls to Classification.[SetField|SetFieldType] to
+        SetFieldInfo.
+
+2003-07-01  Frank Koormann   <frank.koormann at intevation.de>
+
+	MERGE from the greater-ms3 branch.
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_transient_joined_table_with_equal_column_names):
+	New. Test join of two tables with partly equal column names.
+
+	* Thuban/Model/transientdb.py (TransientJoinedTable.create):
+	If duplicates in left and right tables column names are found, 
+	append '_' (underscores) to the name until it is unique.
+	Create always new internal names for the resulting table and reference
+	columns in the join statement with <table>.<column>
+
+2003-07-01  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_transient_joined_table_same_column_name):
+	New. Test whether joining on columns with the same names in both
+	tables works.
+	
+	* Thuban/Model/transientdb.py (TransientJoinedTable.create): Make
+	sure to use the right internal names even when joining on field
+	with the same names in both tables. Also, detect duplicate names
+	in the joined table correctly.
+
+2003-07-01  Frank Koormann   <frank at intevation.de>
+
+	* Thuban/UI/renderer.py (ExportRenderer.render_legend):
+	Reverse List of layers to render in same order as in desktop legend.
+ 
+2003-06-30  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/version.py (make_tuple): Takes a version string
+	and splits it into a tuple of at most three integers.
+	Used make_tuple() to make tuple versions of the version
+	numbers.
+
+	* Thuban/UI/about.py: Add Thuban email addresses.
+
+2003-06-30  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/version.py: SQLite/PySQLite version dependencies
+	were too high.
+
+2003-06-30  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/version.py: Update version to 0.8.1
+	
+	* MANIFEST.in: Added Projections so that default.proj is
+	included.
+
+2003-06-26  Jonathan Coles   <jonathan at intevation.de>
+
+	New About box with lots more information including library
+	versions and credits. More/better version checking before
+	Thuban starts.
+
+	* Thuban/UI/about.py: New. New About box that displays
+	library version information and credits.
+
+	* Thuban/version.py: Added new 'versions' dictionary which
+	contains the verions of various libraries which are checked
+	when the module loads.
+	(verify_versions): Check all version numbers and returns
+	a list of errors.
+
+	* Thuban/UI/classifier.py (Classifier.__EnableButtons):
+	Reset the status of the buttons as the situation warrants,
+	but in a better more reliable way by not relying on the
+	current status to determine what needs to change.
+
+	* Thuban/UI/main.py (wxCHECK_VERSION): Removed. Not needed.
+	(verify_versions): Remove most of the code since it is
+	now in Thuban.version.verify_versions.o
+
+	* Thuban/UI/mainwindow.py (MainWindow.About): Call new
+	About box in Thuban.UI.about.
+
+	* extensions/thuban/gdalwarp.cpp (get_gdal_version): New.
+	Returns the version of gdal library being used as a string.
+
+	* extensions/thuban/wxproj.cpp (check_version, check_version_gtk):
+	Removed.
+	(get_proj_version): Return the version of PROJ that the file
+	was compiled with.
+	(get_gtk_version): Return th version of GTK that the file
+	was compiled with.
+
+2003-06-25  Jonathan Coles   <jonathan at intevation.de>
+ 
+	* Thuban/UI/classifier.py (Classifier.EditSymbol): The parent
+	of the SelectPropertiesDialog should be self so the window
+	appears on top.
+	(ClassGroupPropertiesCtrl.DoEdit): The parent
+	of the SelectPropertiesDialog should be self so the window
+	appears on top.
+
+	* Thuban/UI/resource.py: Cleaned up how we determine file
+	extensions.
+	(GetImageResource): Return an wxImage from our Resources.
+
+2003-06-24  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/renderer.py (ExportRenderer.render_legend):
+	Check that a layer has a classification before trying
+	to get it. Raster layers don't have classifications.
+
+2003-06-23  Jonathan Coles   <jonathan at intevation.de>
+	
+	* setup.py: Add Resources/XML to resource list.
+    
+2003-06-23  Jonathan Coles   <jonathan at intevation.de>
+
+	* setup.cfg: Fix copyright dates
+    
+2003-06-23  Jonathan Coles   <jonathan at intevation.de>
+
+	* MANIFEST.in: Update with Resources/XML
+
+	* setup.py: Don't include Locale resources yet as we don't
+	have any and it causes problems building the distribution
+	for Windows. Update version to 0.8.0.
+
+	* Doc/thuban.dtd: Removed since it is now in Resources/XML.
+
+	* Thuban/UI/mainwindow.py: Add blank line at the end because
+	file was not being read correctly building the Windows
+	distribution.
+
+2003-06-23  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.About): Fix text.
+
+	* Thuban/version.py: Temporarily update longversion for
+	the 0.8 release so that it doesn't have the cvs revision.
+
+2003-06-23  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/common.py (ThubanBeginBusyCursor): Call wxSafeYield
+	to make sure that we don't create reentrant possibilities with
+	wxYield.
+
+	* Thuban/UI/view.py (MapCanvas.OnPaint): Call wxBeginBusyCursor()
+	directly to avoid the wxSafeYield() call which generates an 
+	OnPaint event causing infinite recursion. Don't try to catch
+	exception anymore. This was for before there were limits on map
+	scaling.
+
+2003-06-23  Bernhard Herzog  <bh at intevation.de>
+
+	Bug fix for RT #1961:
+
+	* Thuban/Model/load.py (SessionLoader.start_derivedshapesource):
+	Register DerivedShapestores with the session
+
+	* Thuban/Model/session.py (Session.Tables): Make sure each table
+	is only listed once.
+
+	* test/test_load.py (TestJoinedTable.test): Add check_format call.
+	Update file contents to match the one written out.
+
+2003-06-20  Bernhard Herzog  <bh at intevation.de>
+
+	* test/xmlsupport.py (SaxEventLister.startElementNS)
+	(SaxEventLister.endElementNS): Do not include the qname. Python
+	2.2.1 and 2.2.2 and 2.2.3 differ in this regard. In 2.2.1 qname it
+	is (presumably incorrectly) None, whereas it's a string with the
+	element name in the later versions.
+
+	* test/test_xmlsupport.py (TestEventList.test_even_list_simple)
+	(TestEventList.test_even_list_namespace): Update tests to reflect
+	the new behaviour
+	(TestEventList.test_even_list_id_normalization): Fix doc-string
+
+2003-06-20  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/layer.py (BaseLayer.HasShapes): New. Overridden
+	by deriving classes to determine if that layer supports shapes.
+	(Layer): Override HasShapes and return true.
+
+	* Thuban/UI/classgen.py: Use Thuban[Begin|End]BusyCursor()
+	instead of a direct call to wx[Begin|End]CusyCursor().
+	(GenUniquePanel._OnRetrieve): Set busy cursor while retrieving
+	table data.
+
+	* Thuban/UI/common.py (ThubanBeginBusyCursor, ThubanEndBusyCursor):
+	New. Wrappers around the wxWindows functions that allow us to 
+	make additional calls such as wxYield which gives the native 
+	system a chance to update the cursor correctly.
+
+	* Thuban/UI/tableview.py: Use Thuban[Begin|End]BusyCursor()
+        instead of a direct call to wx[Begin|End]CusyCursor().
+
+	* Thuban/UI/view.py: Use Thuban[Begin|End]BusyCursor()
+	instead of a direct call to wx[Begin|End]CusyCursor().
+	(MapCanvas.find_shape_at): Check if the current search layer
+	support shapes, otherwise go on to the next layer.
+
+	* test/test_layer.py: Add tests in each type of layer for
+	HasClassification() and HasShapes()
+
+2003-06-20  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/view.py (MapCanvas.OnPaint): Call wxYield after
+	turning on the busy cursor to allow the system to change the
+	cursor before we begin painting. This fixes a problem that
+	was occuring only under GTK. Fixes RTbug #1840.
+
+2003-06-20  Bernhard Herzog  <bh at intevation.de>
+
+	* Resources/XML/thuban-0.8.dtd: New DTD for the new file format
+	version.
+
+	* Thuban/Model/save.py (sort_data_stores): New. Make topological
+	sort of the data sources so they can be written with sources that
+	data sources that depend on other data sources come after the
+	sources they depend on.
+	(SessionSaver.__init__): Add idmap instance variable to map from
+	objects to the ids used in the file.
+	(SessionSaver.get_id, SessionSaver.define_id)
+	(SessionSaver.has_id): New. Methods to manage the idmap
+	(SessionSaver.write): Use thuban-0.8.dtd
+	(SessionSaver.write_session): Add a namespace on the session and
+	write out the data sources before the maps.
+	(SessionSaver.write_data_containers): New. Write the data
+	containers.
+	(SessionSaver.write_layer): Layer elements now refer to a
+	shapestore and don't contain filenames anymore.
+
+	* Thuban/Model/load.py (LoadError): Exception class to raise when
+	errors in the files are discovered
+	(SessionLoader.__init__): Define dispatchers for elements with a
+	thuban-0.8 namespace too.
+	(SessionLoader.check_attrs): New helper method to check and
+	convert attributes
+	(AttrDesc): New. Helper class for SessionLoader.check_attrs
+	(SessionLoader.start_fileshapesource)
+	(SessionLoader.start_derivedshapesource)
+	(SessionLoader.start_filetable, SessionLoader.start_jointable):
+	Handlers for the new elements in the new fileformat
+	(SessionLoader.start_layer): Handle the shapestore attribute in
+	addition to filename.
+	(SessionLoader.start_table, SessionLoader.end_table): Removed.
+	They were never used in the old formats and aren't needed for the
+	new.
+
+	* Thuban/Model/session.py (Session.DataContainers): New method to
+	return all "data containers", i.e. shapestores and tables
+
+	* test/xmlsupport.py (SaxEventLister.__init__)
+	(SaxEventLister.startElementNS, sax_eventlist): Add support to
+	normalize IDs.
+
+	* test/test_xmlsupport.py
+	(TestEventList.test_even_list_id_normalization): New test case for
+	id normalization
+
+	* test/test_load.py (LoadSessionTest.check_format): Use ID
+	normalization
+	(LoadSessionTest.thubanids, LoadSessionTest.thubanidrefs): New
+	class atrributes used for ID normalization
+	(TestSingleLayer, TestLayerVisibility, TestLabels.test)
+	(TestLayerProjection.test, TestRasterLayer.test): Adapt to new
+	file format
+	(TestJoinedTable): New test for loading sessions with joined
+	tables.
+	(TestLoadError): New. Test whether missing required attributes
+	cause a LoadError.
+
+	* test/test_save.py (SaveSessionTest.thubanids)
+	(SaveSessionTest.thubanidrefs): New class attributes for ID
+	normalization in .thuban files.
+	(SaveSessionTest.compare_xml): Use id-normalization.
+	(SaveSessionTest.testEmptySession)
+	(SaveSessionTest.testLayerProjection)
+	(SaveSessionTest.testRasterLayer)
+	(SaveSessionTest.testClassifiedLayer): Adapt to new file format.
+	(SaveSessionTest.testLayerProjection): The filename used was the
+	same as for testSingleLayer. Use a different one.
+	(SaveSessionTest.test_dbf_table)
+	(SaveSessionTest.test_joined_table): New test cases for saving the
+	new data sources structures.
+	(TestStoreSort, MockDataStore): Classes to test the sorting of the
+	data stores for writing.
+
+	* test/runtests.py: Add CVS keywords
+
+2003-06-20  Jonathan Coles   <jonathan at intevation.de>
+
+	* test/test_session.py
+	(UnreferencedTablesTests.test_unreferenced_tables_with_joins):
+	Use the cultural_landmark-point.dbf file for the store so that
+	the table rows and shape count match.
+
+2003-06-20  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/data.py (DerivedShapeStore.__init__): Raise
+	an exception if the number of shapes is different from the
+	number of rows in the table. Address RTbug #1933.
+
+	* test/test_layer.py (TestLayer.test_derived_store): Add
+	a test for the new exception in DerivedShapeStore.__init__.
+
+	* test/support.py (FloatTestCase): Removed since there is
+	already FloatComparisonMixin. Fixes RTbug #1954.
+	(FloatComparisonMixin.assertFloatEqual): Include test for
+	infinity that was part of FloatTestCase.
+
+	* test/test_range.py (RangeTest): Inherit from
+	support.FloatComparisonMixin now that we don't have
+	support.FloatTestCase.
+
+2003-06-20  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_save.py (SaxEventLister, sax_eventlist): Removed. Use
+	the implementation in xmlsupport instead.
+	(SaveSessionTest.compare_xml): sax_eventlist is now in xmlsupport
+
+	* test/test_proj.py: Import sax_eventlist from xmlsupport instead
+	of test_save
+
+2003-06-20  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_load.py (LoadSessionTest.check_format): New helper
+	method to make sure the test files we load might have been written
+	by the current thuban version.
+	(ClassificationTest.TestLayers, TestSingleLayer.test)
+	(TestLayerVisibility.test, TestClassification.test)
+	(TestLabels.test, TestLayerProjection.test, TestRasterLayer.test):
+	Add check_format() calls and fix the thuban data to match the data
+	that would be written by saving the session loaded from it.
+
+	* test/xmlsupport.py (SaxEventLister, sax_eventlist): Copies of
+	the same class and function in test_save.
+
+	* test/test_xmlsupport.py (TestEventList): New. test cases for
+	sax_eventlist
+
+2003-06-20  Bernhard Herzog  <bh at intevation.de>
+
+	* Resources/XML/thuban.dtd: Add comment about which versions of
+	Thuban are covered by this DTD
+	(map): Fix content model for layers and raster layers. There can
+	be any number or layers and raster layers in any order.
+
+2003-06-20  Jonathan Coles   <jonathan at intevation.de>
+
+	This is mainly about fixing RTbug #1949.
+
+	* Thuban/Model/classification.py: Remove "from __future__"
+	import statement since python 2.2 is the earliest supported
+	version.
+
+	* Thuban/Model/proj.py (Projection.GetProjectedUnits): New.
+	Currently returns PROJ_UNITS_METERS or PROJ_UNITS_DEGREES
+	depending on the units this projection *forwards* into.
+
+	* Thuban/Model/save.py (SessionSaver.write_classification):
+	Remove unnecessary use of lambdas and nested functions.
+
+	* Thuban/UI/legend.py (ScaleBarBitmap.__SetScale): Do scale
+	adjustment here if the map projection uses degrees.
+
+	* Thuban/UI/scalebar.py (ScaleBar.DrawScaleBar): Remove
+	scale adjust code since it is now done before calling
+	this method. Don't do anything if the map projection
+	is None.
+
+2003-06-19  Bernhard Herzog  <bh at intevation.de>
+
+	Move version specific load tests to their own file.
+
+	* test/test_load.py: Expand the doc-string to explain a bit how to
+	handle file format changes.
+	(TestClassification.test): Update the docstring as this test is
+	not about Thuban 0.2 anymore.
+
+	* test/test_load_0_2.py: New file with the load tests for thuban
+	files created with Thuban 0.2 and earlier.
+
+2003-06-19  Bernhard Herzog  <bh at intevation.de>
+
+	Add XML validation to some of the tests. Validation will only be
+	done if pyRXP is installed (http://reportlab.com/xml/pyrxp.html).
+	To make the DTD available to the test cases it's moved into
+	Resources/XML
+
+	* Resources/XML/thuban.dtd: New. This is now the real Thuban DTD
+	for versions up to and including 0.2. Two slight changes: added an
+	encoding specification and fixed the comment which refered to
+	GRASS, not Thuban
+
+	* test/xmlsupport.py: New support module for tests involving XML.
+	Currently there's a mix-in class for XML validation.
+
+	* test/test_xmlsupport.py: New. Tests for the xmlsupport module
+
+	* test/test_save.py (SaveSessionTest): Derive from ValidationTest
+	so that we can validate the
+	(SaveSessionTest.testEmptySession)
+	(SaveSessionTest.testSingleLayer)
+	(SaveSessionTest.testSingleLayer)
+	(SaveSessionTest.testLayerProjection)
+	(SaveSessionTest.testRasterLayer)
+	(SaveSessionTest.testClassifiedLayer): Validate the generated XML
+
+	* test/runtests.py (main): Call print_additional_summary instead
+	of print_garbage_information
+
+	* test/support.py (resource_dir): New function to return the
+	"Resource" subdirectory
+	(print_additional_summary): New function to combine several
+	summary functions
+	(run_tests): Use print_additional_summary instead of calling
+	print_garbage_information directly
+
+2003-06-19  Bernhard Herzog  <bh at intevation.de>
+
+	* Doc/thuban.dtd (classification): Correct the content model of
+	the classification element.
+	(projection): Add the "name" attribute
+
+2003-06-19  Frank Koormann   <frank.koormann at intevation.de>
+
+	MERGE from the greater-ms3 branch.
+
+	* Thuban/UI/scalebar.py (ScaleBar.DrawScaleBar): Apply conversion to
+	scale if projection is latlong to get better estimate.
+
+	Fix problem of hidden properties dialog under windows after double
+	click on layer tree:
+	The tree control always gets an Expanded / Collapsed event after 
+	the ItemActivated  on double click, which raises the main window again.
+ 	We add a second ItemActivated event to the queue, which simply 
+	raises the already displayed window.
+
+	* Thuban/UI/legend.py (LegendTree.__init__): Instance variable 
+	raiseProperties initialized to prevent endless loops
+	(LegendTree._OnItemActivated): Depending on self.raiseProperties
+	simply raise the properties or open the dialog and issue a second
+	event.
+
+2003-06-18  Jonathan Coles   <jonathan at intevation.de>
+
+	* setup.py: Fix a few problems that occured under Windows.
+
+2003-06-18  Jonathan Coles   <jonathan at intevation.de>
+
+	When Thuban loaded the map was redrawn twice because the
+	legend was being opened after the mainwindow was created
+	and not during its creation. This meant the map was drawn
+	initially and then had to be redrawn when the legend 
+	caused the display to change. Now the legend is opened
+	in the mainwindow constructor which resolves this issue.
+
+	Also, although we were checking for the existence of 
+	gdal and gdalwarp modules, the gdalwarp extension was
+	still being compiled (which may fail if the system doesn't
+	have gdal installed). the build_ext command to setup.py
+	now accepts the flags --with-gdal and --without-gdal.
+	If --without-gdal is specified setup.py will try to 
+	use the gdal parameters specified by gdal-config. Under
+	windows, those parameters have to be set in setup.py
+	as with proj4 an wxWindows.
+
+	* setup.py: Use a list instead of seperate variables for
+	extension parameters so we can create a generic function
+	that runs an appropriate *-config script.
+	(run_cs_script): Renamed from run_wx_script and modified
+	to accept a second argument which is a list of lists to
+	be filled in by the values returned from running the command.
+	(thuban_build_ext): New. Extends the build_ext command and
+	provides the options --with-gdal/--without-gdal which then
+	optionally includes the gdalwarp extension.
+
+	* Thuban/Model/resource.py: First check if we can import
+	the gdalwarp Thuban extension before checking for gdal.
+	Also added some comments.
+	
+	* Thuban/UI/legend.py (ScaleBarBitmap.__SetScale): Check if
+	the map is None which may be the case if none has been loaded
+	yet.
+
+	* Thuban/UI/main.py (main): Remove call to ShowLegend.
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): Call ShowLegend().
+
+	* Thuban/UI/renderer.py: Check for gdal support before importing
+	gdalwarp.
+	(MapRenderer.render_map): Only try to optimize if we have gdal
+	support otherwise nothing will get drawn.
+
+	* Thuban/UI/view.py (MapCanvas.FitMapToWindow): This may be called 
+	during startup before a map has been created. Check if map is None 
+	before using it and do nothing if it is.
+
+2003-06-17  Jonathan Coles   <jonathan at intevation.de>
+
+	Fix the problem with raster layers under Windows that caused
+	Thuban to crash. The view should respond to layer projection
+	changed events to update the display. Changes to a projection
+	should not cause the map to be set to full extent.
+	
+	* Thuban/UI/view.py (MapCanvas.__init__): New instance variable
+	current_map_proj to remember the current map projection so that
+	when the projection changes we know what the previous projection
+	was. 
+	(MapCanvas.SetMap): Unsubscribe and subscribe to 
+	LAYER_PROJECTION_CHANGED events.
+	(MapCanvas.projection_changed): Split into two methods that respond
+	to map and layer projection changes.
+	(MapCanvas.map_projection_changed): New. Takes the current view and
+	projects it using the new projection. This does not cause the
+	map to be redrawn at full extent.
+	(MapCanvas.layer_projection_changed): New. Cause a redraw which
+	will draw each layer in its new projection.
+	
+	* extensions/thuban/bmpdataset.cpp (BMPDataset::Open): Call
+	VSIFClose() not VSIFCloseL() to close the file. Fixes a crash
+	under Windows.
+	
+	* extensions/thuban/gdalwarp.cpp (MFILENAME): Padding should be
+	to twice sizeof(void*) because there are two digits for each
+	hex byte.
+
+2003-06-16  Bernhard Herzog  <bh at intevation.de>
+
+	Update to the layer interface: Direct access to the table,
+	shapetable, shapefile and filename attributes is now actively
+	deprecated by issuing deprecation warnings for all places where
+	this happens.
+
+	* Thuban/Model/layer.py (Layer.__getattr__): New. Implement access
+	to the instance variables table, shapetable, shapefile and
+	filename via __getattr__ so that we can issue a deprecation
+	warning.
+	(Layer.SetShapeStore): Don't set the deprecated instance variables
+	any more
+	(Layer.SetShapeStore): Don't use deprecated layer instance
+	variables
+	(Layer.Destroy): No need to explicitly remove the instance
+	variables any more
+	(Layer.GetFieldType, Layer.Shape): Don't use deprecated layer
+	instance variables
+
+	* Thuban/UI/classgen.py (ClassGenDialog.__init__)
+	(GenUniformPanel._OnRetrieve, GenUniquePanel._OnRetrieve)
+	(GenQuantilesPanel.GetList, GenQuantilesPanel.OnRetrieve): Don't
+	use deprecated layer instance variables
+
+	* Thuban/UI/classifier.py (Classifier.__init__): Don't use
+	deprecated layer instance variables
+
+	* Thuban/UI/identifyview.py (IdentifyListCtrl.selected_shape)
+	(IdentifyGridCtrl.selected_shape): Don't set the deprecated layer
+	instance variables
+
+	* Thuban/UI/tableview.py (LayerTableGrid.select_shapes): Don't use
+	deprecated layer instance variables
+
+	* Thuban/UI/mainwindow.py (MainWindow.LayerShowTable): Don't use
+	deprecated layer instance variables
+
+	* Thuban/Model/save.py (SessionSaver.write_layer): Don't use
+	deprecated layer instance variables
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer)
+	(MapRenderer.polygon_render_param): Don't use deprecated layer instance
+	variables
+
+	* test/runtests.py (main): Turn Thuban's deprecation warnings into
+	errors so that they're cought by the tests
+
+	* test/test_load.py (TestSingleLayer.test): Don't use deprecated
+	layer instance variables
+
+2003-06-16  Jonathan Coles   <jonathan at intevation.de>
+
+	Fix a problem under Windows whereby if the user double-clicks on a
+	layer in the legend that tree item will expand or collapse as well
+	as open the layer properties dialog. The state of the tree item
+	should not be affected.
+
+	* Thuban/UI/legend.py (LegendTree.__init__): Add instance variable
+	preventExpandCollapse and subscribe to expanding and collapsing 
+	events.
+	(LegendTree.OnItemExpandCollapse): New. Responds to expanding and 
+	collapsing events and will veto the event if it has been triggered 
+	by the user double clicking on a layer.
+	(LegendTree._OnItemActivated): Set preventExpandCollapse to indicate
+	that an expanding/collapsing event should be vetoed.
+
+2003-06-13  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/classifier.py (Classifier.OnClose)
+	(Classifier.map_layers_removed)
+	(Classifier.layer_shapestore_replaced): Unsubscribe the messages
+	in OnClose and not in map_layers_removed or
+	layer_shapestore_replaced to make sure it always happens when the
+	dialog is closed
+
+2003-06-13  Jonathan Coles   <jonathan at intevation.de>
+
+	This puts back a fix for Windows where a panel is needed so that
+	the background of the table view appears correctly.
+
+	* Thuban/UI/tableview.py (TableFrame.__init__): Add a panel
+	object that can be used by derived classes to place any 
+	controls (including the grid) onto.
+	(QueryTableFrame.__init__): Use the panel as the parent window
+	for all the controls. Reparent the grid so that the panel is
+	the parent. Call UpdateStatusText() to correctly initialize
+	the status bar.
+
+2003-06-13  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/dialogs.py (ThubanFrame): New: a class that inherits
+	from wxFrame (as opposed to wxDialog like the other classes)
+	but otherwise behaves like the other classes. This is needed
+	for the TableView which isn't really a dialog and needs to
+	have a status bar and control buttons.
+
+	* Thuban/UI/tableview.py (TableGrid.__init__): Create an 
+	instance variable to keep track of how many rows are selected.
+	Subscribe once to the the events we are interested in.
+	(ThubanGrid.OnRangeSelect): Only handle event if event handling
+	hasn't been turned off.
+	(ThubanGrid.OnSelectCell): Only handle event if event handling
+	hasn't been turned off.
+	(ThubanGrid.ToggleEventListeners): Rather than subscribe None
+	as an event listener (which changes the event handler stack)
+	simply set an instance variable to False. This is checked in
+	the event handlers.
+	(ThubanGrid.GetNumberSelected): Return the number of currently
+	selected rows.
+	(TableFrame): Inherit from ThubanFrame so we can have a 
+	status bar and control buttons.
+	(QueryTableFrame.__init__): Create a status bar. Fixes RTbug #1942.
+	Explicitly set which items are selected in the operator choice and
+	action choice so there is always a valid selection. Fixes RTbug #1941.
+	Subscribe to grid cell selection events so we can update the
+	status bar.
+	(QueryTableFrame.UpdateStatusText): Update the status bar with
+	how many rows are in the grid, how many columns, and how many
+	rows are selected.
+	(QueryTableFrame.OnGridSelectRange, QueryTableFrame.OnGridSelectCell):
+	Call UpdateStatusText when cells are (de)selected.
+	(QueryTableFrame.OnQuery): Use the string value in the value
+	combo if either the selected item index is 0 or if the string
+	cannot be found in the predefined list (this happens if the
+	user changes the text). Fixes RTbug #1940.
+	Only turn off the grid event listeners if there a query comes
+	back with a none empty list of ids. in the case that the list
+	is empty this causes a grid.ClearSelection() call to actually
+	clear the grid selection which causes the selected items in
+	the map to be deselected. Fixes RTbug #1939.
+
+	* test/test_save.py (XMLWriterTest.Encode): Check return values.
+	Fixes RTbug #1851.
+
+2003-06-13  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/identifyview.py (IdentifyView.__init__): Call
+	self.selected_shape with the current selection to make sure the
+	contents of the dialog are up to date when it's shown for the
+	first time.
+	The dialog used to work without this by luck. The recent fix to
+	the connector module 'broke' a 'feature' the identify view was
+	relying on, i.e that subscribing to a message in response to
+	receiving a message of that type would mean that the new
+	subscriber would also be called for the same message.
+	
+2003-06-12  Jonathan Coles   <jonathan at intevation.de>
+
+	* extensions/thuban/gdalwarp.cpp: Removed debug printing as
+	the image is rendered. Fixes RTbug #1937.
+
+2003-06-12  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Lib/fileutil.py: As is done under Windows, create the
+	user directory if it doesn't exist on a posix system. 
+	Fixes RTbug #1815.
+
+	* Thuban/Model/resource.py (get_user_proj_files): Moved the
+	called to get_application_dir here, so that the directory
+	will only be called if this method is invoked.
+
+	* Thuban/UI/projdialog.py (ProjFrame.__DoOnProjAvail): Clear
+	the projfilepath if no projection is selected.
+
+2003-06-12  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/legend.py (ScaleBarBitmap.__SetScale): Don't draw
+	the scalebar if the current map has no projection set.
+
+	* Thuban/UI/projdialog.py (ProjFrame.__DoOnProjAvail): Set the
+	projfilepath label to just the basename of the projection file
+	rather than include the entire path.
+
+	* Thuban/Model/resource.py: Fix missed proj functions that 
+	needed to be renamed.
+
+2003-06-12  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py: Removed assert statements that
+	tested if the variable was an instance of Color. 
+
+	* Thuban/Model/color.py (Color): Remove commented code that isn't
+	used.
+	(Transparent): Renamed from NoColor. Doesn't inherit from Color.
+	Fixes RTbug #1835.
+	(Transparent.__eq__, Transparent.__ne, Transparent.__repr): New.
+	Needed now that the class doesn't inherit from Color.
+
+2003-06-12  Jonathan Coles   <jonathan at intevation.de>
+
+	* test/test_save.py (XMLWriterTest.testEncode): Explicitly
+	check unicode strings.
+
+	* test/test_layer.py: Check for existence of gdal.
+
+2003-06-12  Jonathan Coles   <jonathan at intevation.de>
+    
+	* Thuban/Model/xmlreader.py: New. Contains the XMLReader class
+	that was in load.py
+
+	* Thuban/Model/xmlwriter.py: New. Contains the XMLWriter class
+	that was in save.py
+
+2003-06-12  Jonathan Coles   <jonathan at intevation.de>
+
+	This is largely a collection of bug fixes. We also handle the
+	case where gdal is not on the system. The XMLReader and XMLWriter
+	classes were moved into there own files to resolve some circular
+	import references and because they shouldn't really be in the
+	file that is dediciated to reading/writing session files since
+	they are also used elsewhere.
+
+	* Thuban/Model/classgen.py: Renamed functions to follow the
+	function_names_with_underscores style. Fixes RTbug #1903.
+	(calculate_quantiles): Raise ValueError if 'percents' is invalid.
+
+	* Thuban/Model/layer.py: Import gdal only if it available.
+	(RasterLayer): Handle the case where the gdal library is unavailable.
+	Addresses RTbug #1877.
+
+	* Thuban/Model/load.py (XMLReader): Moved into seperate file
+	xmlreader.py.
+
+2003-06-12  Jonathan Coles   <jonathan at intevation.de>
+
+	This is largely a collection of bug fixes. We also handle the
+	case where gdal is not on the system. The XMLReader and XMLWriter
+	classes were moved into there own files to resolve some circular
+	import references and because they shouldn't really be in the
+	file that is dediciated to reading/writing session files since
+	they are also used elsewhere.
+
+	* Thuban/Model/classgen.py: Renamed functions to follow the
+	function_names_with_underscores style. Fixes RTbug #1903.
+	(calculate_quantiles): Raise ValueError if 'percents' is invalid.
+
+	* Thuban/Model/layer.py: Import gdal only if it available.
+	(RasterLayer): Handle the case where the gdal library is unavailable.
+	Addresses RTbug #1877.
+
+	* Thuban/Model/load.py (XMLReader): Moved into seperate file
+	xmlreader.py.
+
+	* Thuban/Model/save.py (escape, XMLWriter): Moved into seperate
+	file xmlwriter.py.
+
+	* Thuban/Model/resource.py: Renamed functions to following the
+	function_names_with_underscores style.
+	(has_gdal_support): New function that returns true if the gdal 
+	library is available. Addresses RTbug #1877.
+
+	* Thuban/UI/application.py (ThubanApplication.OpenSession):
+	Display a message box if the gdal library is not available, but
+	only if there are any layers that would use it. Addresses RTbug #1877.
+
+	* Thuban/UI/classgen.py: Use renamed projection resource functions.
+	(GenUniformPanel.__CalcStepping): Fix a slight discrepency 
+	when using integers versus floats.
+
+	* Thuban/UI/mainwindow.py (_has_gdal_support): New. Used to
+	determine if the "Add Image Layer" menu option should be 
+	greyed out or not. Addresses RTbug #1877.
+
+	* Thuban/UI/projdialog.py: Use renamed projection resource functions.
+
+	* Thuban/UI/renderer.py (MapRenderer.render_map): Only try to 
+	optimize if a raster layer is visible. Fixes RTbug #1931.
+	Only draw the raster layer if the gdal library is available.
+	Addresses RTbug #1877.
+
+	* test/test_classgen.py: Add tests for generate_singletons,
+	generate_uniform_distribution, generate_quantiles. Fixes RTbug #1903.
+	(test_calculate_quantiles): Fix some tests to catch the new
+	ValueError that is raised.
+
+	* test/test_proj.py: Use renamed projection resource functions.
+
+	* test/test_save.py (SaveSessionTest.testClassifiedLayer): New
+	test for saving classified layers. Fixes RTbug #1902.
+	(XMLWriterTest): New. Tests the XMLWriter class. Fixes RTbug #1851.
+
+2003-06-12  Jan-Oliver Wagner <jan at intevation.de>
+
+	Fix for http://intevation.de/rt/webrt?serial_num=1900.
+
+	* Thuban/UI/multiplechoicedialog.py: New. A multiple choice dialog.
+
+	* Thuban/UI/mainwindow.py: import wxMultipleChoiceDialog from
+	multiplechoicedialog.py rather than from the wxPython library.
+
+2003-06-11  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/Lib/fileutil.py (get_application_dir): Minor stability
+	update.
+
+2003-06-11  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/Lib/fileutil.py (get_application_dir): New function to
+	determine the absolute .thuban/thuban directory under 
+	"posix" (os.expanduser) and "nt" (read AppData registry key). 
+
+	* Thuban/Model/resource.py: Use get_application_dir
+
+	* Thuban/UI/application.py (ThubanApplication.read_startup_files): 
+	Use get_application_dir.
+
+2003-06-10  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/tableview.py (LayerTableFrame.__init__): Subscribe to
+	the messages MAP_LAYERS_REMOVED messages
+	(LayerTableFrame.OnClose): Unsubscribe from it.
+	(LayerTableFrame.map_layers_removed): New. Receiver for
+	MAP_LAYERS_REMOVED. Close the dialog when the layer whose the
+	dialog is showing is removed.
+
+2003-06-10  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Lib/connector.py (Connector.Issue): Iterate over a copy
+	of the receivers list so that unsubscribing in a receiver doesn't
+	modify it while iterating over it.
+
+	* test/test_connector.py
+	(ConnectorTest.test_disconnect_in_receiver): New. Test whether
+	unsubscribing in a receiver works correctly. See docstring for
+	details
+
+2003-06-10  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/messages.py (LAYER_SHAPESTORE_REPLACED): New
+	message.
+
+	* Thuban/Model/layer.py (Layer.SetShapeStore): Send
+	LAYER_SHAPESTORE_REPLACED when the shapestore changes. A
+	LAYER_CHANGED will still be sent if the classification changes.
+
+	* Thuban/UI/classifier.py (Classifier.__init__): Add the map as
+	parameter so we can subscribe to some of its messages
+	(Classifier.__init__): Subscribe to the map's MAP_LAYERS_REMOVED
+	and the layer's LAYER_SHAPESTORE_REPLACED
+	(Classifier.unsubscribe_messages): New. Unsubscribe from message
+	subscribed to in __init__
+	(Classifier.map_layers_removed)
+	(Classifier.layer_shapestore_replaced): receivers for the messages
+	subscribed to in __init__. Unsubscribe and close the dialog
+
+	* Thuban/UI/mainwindow.py (MainWindow.OpenLayerProperties): Pass
+	the map to the Classifier dialog
+
+	* test/test_layer.py (SetShapeStoreTests): Derive from
+	SubscriberMixin as well so we can test messages
+	(SetShapeStoreTests.setUp): Subscribe to some of the layer's
+	messages
+	(SetShapeStoreTests.tearDown): Clear the messages again
+	(SetShapeStoreTests.test_sanity): Expand the doc-string and check
+	for the modified flag too
+	(SetShapeStoreTests.test_set_shape_store_modified_flag): New test
+	to check whether SetShapeStore sets the modified flag
+	(SetShapeStoreTests.test_set_shape_store_different_field_name)
+	(SetShapeStoreTests.test_set_shape_store_same_field)
+	(SetShapeStoreTests.test_set_shape_store_same_field_different_type):
+	Add tests for the messages. This checks both the new
+	LAYER_SHAPESTORE_REPLACED and the older LAYER_CHANGED
+
+2003-06-06  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/mainwindow.py: Improved and partly added help texts for
+	the menu items.
+
+2003-06-05  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/UI/identifyview.py (IdentifyView.__init__):
+	Layout reimplemented without panel. Make life easier to fit the list
+	in the dialog.
+
+2003-06-05  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/UI/projdialog.py (ProjFrame.__init__): Fill the projchoice
+	once on initialisation (Former implementation resulted in multiple
+	entries for each projection).
+	(ProjFrame.__FillAvailList): selectProj as second optional parameter, 
+	if set, select the projection found under the specified name. This 
+	overwrites any other selection estimate.
+	Removed projchoice filling from this method.
+	(ProjFrame._OnSave, ProjFrame._OnAddToList): 
+	Updated call of ProjFrame.__FillAvailList
+	(LCCPanel._DoLayout): Moved parameter controls in more common order.
+
+	* Resources/Projections/defaults.proj: Extended defaults representing
+	various common European projections.
+
+2003-06-05  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/UI/identifyview.py (IdentifyView.__init__): 
+	Use ListCtrl instead of GridCtrl
+
+	* Thuban/Model/resource.py: 
+	Guess location of .thuban directory from tempdir parent directory.
+
+	* Thuban/UI/application.py (ThubanApplication.read_startup_files):
+	Guess location of .thuban directory from tempdir parent directory.
+
+2003-06-04  Bernhard Herzog  <bh at intevation.de>
+
+	Do not cache the values returned by the tree widget's
+	GetFirstChild and GetNextChild methods because it led to lots of
+	segfaults. The new way requires more brute force but is more
+	reliable.
+
+	* Thuban/UI/legend.py (LegendTree.__init__): Remove instance
+	variable layer2id
+	(LegendTree.find_layer): New method to do with brute force what
+	layer2id tried to accomplish
+	(LegendTree._OnMsgLayerChanged)
+	(LegendTree._OnMsgLayerTitleChanged, LegendTree.__ShowHideLayer):
+	Use find_layer instead of layer2id
+	(LegendTree.__RemoveLayer, LegendTree.__AddLayer): No need to
+	update layer2id anymore
+	(LegendTree._OnMsgMapLayersRemoved) 
+	(LegendTree._OnMsgMapLayersAdded): Get by without layer2id.
+
+2003-06-03  Thomas Koester  <tkoester at intevation.de>
+
+	* Thuban/Model/classgen.py (GenQuantiles0): New function.
+
+2003-06-02  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (layer_rename command, table_rename command):
+	New commands.
+	(main_menu): Add the new commands.
+	(MainWindow.TableRename): New. Implementation of the table_rename
+	command.
+	(MainWindow.RenameLayer): New. Implementation of the layer_rename
+	command.
+
+	* Thuban/Model/session.py (Session.AddTable): call self.changed to
+	set the modified flag
+
+	* test/test_session.py (TestSessionSimple.test_add_table): Test
+	whether the modified flag is set properly
+
+	* Thuban/Model/base.py (TitledObject.SetTitle): Call changed
+	instead of issue so that the modified flags get updated.
+
+	* test/test_base.py (SomeTitledObject): Derive from Modifiable
+	instead of Publisher to reflect reality better and to accomodate
+	the fact that SetTitle now calls changed instead of issue
+
+2003-06-02  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/classgen.py (GenQuantilesPanel.GetList): Resource
+	acquisition has to happen before the try in a try-finally.
+
+2003-06-02  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/legend.py (LegendTree._OnMsgMapLayersRemoved): It's
+	possible that a layer is removed that is not currently selected in
+	the legend so don't check for this.
+
+2003-05-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.Destroy): Set all instance
+	variables to None that have direct or indirect references to
+	shapefiles or dbf files to make sure that they do go away and the
+	files are closed.
+
+2003-05-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/legend.py (LegendTree.GetRootItem): Reset
+	availImgListIndices when a new image list is created
+	
+2003-05-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/legend.py (LegendTree.__init__): New instance variable
+	changing_selection to indicate whether the LegendTree code itself
+	is currently changing the selection
+	(LegendTree.normalize_selection): New method to normalize the
+	selection by selecting the layer item even if the user clicked on
+	the classification.
+	(LegendTree._OnSelChanged): normalize the selection. This works
+	around a bug in wx which doesn't keep track of the selection
+	properly when subtrees are deleted.
+
+2003-05-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py (MapCanvas.set_view_transform): Limit the
+	maximum and minimum scale factors.
+
+	* test/test_classgen.py (ClassGenTest.test): Update to reflect the
+	changes in classgen.py
+
+2003-05-30  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classgen.py: Remove ClassGenerator class but make
+	all the methods functions. Fixes RTBug #1903.
+
+	* Thuban/Model/map.py (Map.TopLayer, Map.BottomLayer): Renamed
+	to MoveLayerToTop and MoveLayerToBottom respectively. Fixes
+	RTBug #1907.
+
+	* Thuban/UI/classgen.py: Use classgen functions that were part
+	of the ClassGenerator class. Put try/finally blocks around
+	code that uses wxBeginBusyCursor()/wxEndBusyCursor(). Fixes
+	RTBug #1904.
+
+	* Thuban/UI/classifier.py: Remove unused import of ClassGenerator.
+
+	* Thuban/UI/legend.py: The legend was cleared and repopulated any
+	time something changed which caused some state to be lost such
+	as which children were expanded or collapsed. Fixes RTBug #1901.
+	(LegendTree._OnMsgMapLayersAdded): Add only new layers.
+	(LegendTree.__OnMsgMapLayersRemoved): Remove layers that exist in 
+	the legend but not in the map.
+	(LegendTree.__FillTree): Move main functionality out into smaller
+	methods that can be used by other methods.
+	(LegendTree.__FillTreeLayer): Reuse old slots in the image list
+	if they are available.
+	(LegendTree.DeleteAllItems): Renamed from __DeleteAllItems so
+	that we override the wxTreeCtrl method. Iterate over children
+	and call __RemoveLayer.
+	(LegendTree.__AddLayer): New. Add a new layer to the legend.
+	(LegendTree.__RemoveLayer): Remove a layer from the legend.
+	(LegendTree.DeleteChildren): New, overrides wxTreeCtrl method.
+	Should only be called with the id of a layer branch.
+	(LegendTree.GetRootItem): New, overrides wxTreeCtrl method.
+	Returns the root item or creates one if necessary.
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_raster_layer): Call
+	ProjectRasterFile with tuple arguments instead of strings.
+
+	* Thuban/UI/tableview.py (QueryTableFrame.OnQuery): Wrap code
+	with try/finally. Fixes RTBug #1904.
+
+	* Thuban/UI/view.py (MapCanvas.OnPaint): Wrap code
+        with try/finally. Fixes RTBug #1904.
+	(MapCanvas.FitSelectedToWindow): If a single point is selected
+	simply center it on the display. Fixes RTBug #1849.
+
+	* extensions/thuban/gdalwarp.cpp: Removed code that allowed gdalwarp
+	to be compiled as a standalone app. Now the code can only be
+	called from Python which simplifies the parameter passing.
+	(ProjectRasterFile): Handle Python arguments. Remove code that
+	checks for a destination dataset. Add more clean up code.
+
+	* test/test_map.py (TestMapWithContents.test_raise_layer_top,
+	TestMapWithContents.test_lower_layer_bottom): 
+	Test Map.MoveLayerToTop() and Map.MoveLayerToBottom() respectively.
+	Fixes RTBug #1907.
+
+	* Thuban/UI/mainwindow.py (MainWindow.ToggleLegend): Apply a full
+	extent to the map when the legend is toggled. Fixes RTBug #1881.
+
+2003-05-29  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/tableview.py (LayerTableFrame.OnClose): Bug-fix: Now
+	unsubscribes all that is subcribed in __init__.
+
+2003-05-28  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.DuplicateLayer)
+	(MainWindow.CanDuplicateLayer): New methods to implement the
+	Layer/Duplicate command.
+	(layer_duplicate command): New.
+	(main_menu): Add layer_duplicate to the Layer menu.
+
+2003-05-28  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/tableview.py (NullRenderer.Draw): New. Our own
+	renderer so that NULL/None values get displayed differently (by a
+	gray rectangle).
+	(TableGrid.__init__): Override the default renderers
+
+2003-05-28  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.SetShapeStore): Set the
+	classification to "None" if the type of the field has changed.
+
+	* test/test_layer.py (SetShapeStoreTests): New. Class with a few
+	test for the Layer.SetShapeStore method
+
+2003-05-28  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.TreeInfo): Fixed a bug (a layer
+	does not necessarily have a filename).
+
+2003-05-28  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.TableClose, MainWindow.TableShow):
+	sort the selection list for the dialog.
+
+2003-05-28  Frank Koormann  <frank.koormann at intevation.de>
+
+	* extensions/thuban/wxproj.cpp 
+	(project_point): Removed cast to int for projected point coordinates.
+	(shape_centroid): Return last point if all polygon vertices fall 
+	to one point.
+ 
+2003-05-28  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (_can_unjoin): Add doc-string and cope
+	with layers that don't have shapestores, i.e. raster layers.
+
+2003-05-28  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/table.py (DBFTable.__init__): Omit the extension
+	when determining the title from the filename.
+
+	* test/test_dbf_table.py (TestDBFTable.test_title): Update to
+	reflect changes in the way the title is derived from the filename
+
+2003-05-28  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.TableShow): 
+	Added wxDEFAULT_DIALOG_STYLE to show table dialog styles.
+
+2003-05-27  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.delegated_messages): Also
+	delegate SelectedLayer.
+	(MainWindow.LayerUnjoinTable): Implement.
+	(_can_unjoin): New. Helper function for the sensitivity of the
+	layer/unjoin command.
+
+	* Thuban/Model/data.py (ShapefileStore.OrigShapeStore)
+	(DerivedShapeStore.OrigShapeStore): New. Return the original
+	shapestore. Used to figure out how to unjoin.
+	(DerivedShapeStore.Shapefile): Fix a typo.
+
+2003-05-27  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/join.py (JoinDialog): Extend to handle layer joins as
+	well
+	(JoinDialog.__init__): Use the layer parameter and only build the
+	left choice when a layer is given
+	(JoinDialog.OnJoin): Handle layer joins as well
+	(JoinDialog.OnLeftTable, JoinDialog.OnRightTable): Handle the case
+	that the user selects the "Select..." item. The sensitivitly
+	updating is now in update_sensitivity
+	(JoinDialog.y): New method to refactor the sensitivity update of
+	the join button into its own method.
+
+	* Thuban/UI/mainwindow.py (MainWindow.LayerJoinTable): Implement.
+
+2003-05-27  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (table_close command): Make it sensitive
+	iff there are unreferenced tables in the session
+
+2003-05-27  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/messages.py (TABLE_REMOVED): New message.
+
+	* Thuban/Model/session.py (Session.UnreferencedTables): New method
+	to return tables that are not referenced by other tables or shape
+	stores and can be removed.
+	(Session.RemoveTable): Issue a TABLE_REMOVED message after
+	removing the table
+
+	* Thuban/UI/mainwindow.py: Remove unused imports
+	(MainWindow.TableClose): Implement.
+
+	* Thuban/UI/tableview.py (TableFrame.__init__): Subscribe to some
+	messages so that the frame will be automatically closed when a new
+	session is opened or the table is removed.
+	(TableFrame.OnClose): Unsubscribe the Subscriptions made in
+	__init__
+	(TableFrame.close_on_session_replaced)
+	(TableFrame.close_on_table_removed): New. Subscribers that close
+	the window
+
+	* test/test_session.py (TestSessionMessages.test_remove_table)
+	(TestSessionSimple.test_remove_table): Move the test to
+	TestSessionSimple and add test for the TABLE_REMOVED message
+	(TestSessionBase.setUp): Also subscribe to TABLE_REMOVED
+	(TestSessionSimple.test_unreferenced_tables) New. Test for the
+	UnreferencedTables method.
+	(UnreferencedTablesTests): New. Class with some more sophisticated
+	tests for UnreferencedTables.
+
+2003-05-27  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/UI/tableview.py (QueryTableFrame.__init__): The "_S_election"
+	display has some unwanted side effects. Removed again.
+ 
+2003-05-27  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Resources/Bitmaps/legend_icon_layer.xpm: New, icon for legend.
+
+	* Thuban/UI/legend.py (LegendTree.__FillTree): Use "legend_icon_layer" 
+
+2003-05-27  Jan-Oliver Wagner <jan at intevation.de>
+
+	* test/test_menu.py (MenuTest.test): Added test for
+	Menu.RemoveItem().
+
+	* Thuban/UI/menu.py (Menu.RemoveItem): New. Remove an item from
+	the menu.
+
+2003-05-27  Frank Koormann  <frank.koormann at intevation.de>
+	
+	Nonmodal dialogs without parent (i.e. they can fall behind the main
+	window)
+
+	* Thuban/UI/mainwindow.py (MainWindow.OnClose): Explicitly destroy
+	all dialogs in the dialogs dictionary and the canvas.
+
+	* Thuban/UI/dialogs.py (NonModalNonParentDialog): New class, without
+	parent, i.e. can fall behind other windows.
+	(NonModalDialog.OnClose): Check is dialog is in mainwindow.dialog
+	dictionary before removing it.
+
+	* Thuban/UI/classifier.py: Dialog derived from NonModalNonParentDialog
+
+	* Thuban/UI/projdialog.py: Dialog derived from NonModalNonParentDialog
+	* Thuban/UI/tableview.py: Dialog derived from NonModalNonParentDialog
+	* Thuban/UI/tree.py: Dialog derived from NonModalNonParentDialog
+
+2003-05-27  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.ShowTableView): New. Open a
+	tableview dialog
+	(MainWindow.TableShow): Use ShowTableView to open the dialogs.
+	Also, don't use the table's titles as the dialog names. The titles
+	aren't guaranteed to be unique.
+	(MainWindow.TableOpen): Open a table view dialog after opening the
+	table
+
+2003-05-27  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py: Remove the Table/Hide menu item. Its
+	effect can be achieved by simply closing the window showing the
+	table.
+	(MainWindow.TableHide): Removed.
+	(main_menu): Removed "table_hide"
+
+2003-05-27  Frank Koormann  <frank.koormann at intevation.de>
+
+	Fix legend tree display problems under Win32
+
+	* Thuban/UI/legend.py:  BMP_SIZE_W = 15
+	(LegendTree.__FillTree): Display "legend_icon_map.xpm" with layer title.
+	(LegendTree.__FillTreeLayer): Explicitely set SelectedImage.
+
+	* Resources/Bitmaps/legend_icon_map.xpm: New icon for legend.
+
+2003-05-27  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/menu.py (Menu.InsertSeparator): Additional optional parameter
+	'after' now allows to insert separators almost anywhere in the menu.
+
+2003-05-27  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/UI/tableview.py (QueryTableFrame.__init__): Underline the 
+	"S" of selection box label to hint on hot key (Alt-S). Works under 
+	Win32 but is ignored under GTK.
+
+2003-05-26  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/UI/projdialog.py (ProjFrame.__do_layout, ProjPanel._DoLayout):
+	Center Choices.
+
+2003-05-26  Bernhard Herzog  <bh at intevation.de>
+
+	Remove the Precision methods again. They're too DBF specific to be
+	part of the table interface and they're only used in table_to_dbf
+	anyway.
+	
+	* Thuban/Model/transientdb.py (TransientTableBase.Width):Use a
+	fixed precision of 12 for doubles.
+	(TransientTableBase.Precision): Removed
+	(AutoTransientTable.Width): Delegate to self.table.
+
+	* Thuban/Model/table.py (DBFTable.Precision)
+	(MemoryTable.Precision): Removed.
+	(MemoryTable.Width): Use a fixed precision of 12 for doubles.
+	(table_to_dbf): Use a fixed precision of 12 for floats unless the
+	column object specifies something else.
+
+	* test/test_dbf_table.py (TestTableToDBF.test_table_to_dbf): New.
+	test for table_to_dbf
+
+2003-05-26  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_transientdb.py
+	(TestTransientTable.run_iceland_political_tests): Fix a comment.
+
+2003-05-26  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.TableOpen): Real
+	implementation. Mark parts of the file format strings for
+	localization.
+
+	* Thuban/Model/session.py (Session.OpenTableFile): New. Open a dbf
+	file and add the table to the tables managed by the session
+
+	* test/test_session.py (TestSessionSimple.test_open_table_file):
+	New. test case for OpenTableFile
+
+2003-05-26  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/controls.py, Thuban/UI/identifyview.py, Thuban/UI/join.py,
+	Thuban/UI/labeldialog.py, Thuban/UI/mainwindow.py,
+	Thuban/UI/proj4dialog.py, Thuban/UI/tableview.py, Thuban/UI/view.py:
+	Replace the true/false of wxWindows by True/False of Python 2.2.1.
+
+2003-05-26  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/tableview.py (LayerTableFrame.__init__): If there is
+	already a selection present, update the grid accordingly.
+
+	* Thuban/UI/mainwindow.py (MainWindow.TableShow): Make the dialog
+	resizeable and increase its initial size.
+
+2003-05-26  Frank Koormann  <frank.koormann at intevation.de>
+
+	Table export functionality
+
+	* Thuban/Model/table.py (DBFTable.Width, MemoryTable.Width): 
+	Return width (in characters) for a column.
+	(DBFTable.Precision, MemoryTable.Precision): Return decimal precision.
+	(table_to_dbf): Write table to dbf file.
+	(table_to_csv): Write table to csv file.
+
+	* Thuban/Model/transientdb.py (TransientTableBase.Width, 
+	TransientTableBase.Precision): Return column width and precision.
+
+	* Thuban/UI/tableview.py (QueryTableFrame.OnSaveAs): Call table_to_dbf
+	or table_to_csv depending on file selection.
+
+	* test/test_dbf_table.py: 
+	Test table_to_dbf (extension of former part of test).
+
+	* test/test_csv_table.py:
+	Test table_to_csv.
+
+2003-05-23  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/join.py (JoinDialog.OnJoin): Use _() for strings.
+	Use QueryTableFrame instead of TableFrame.
+
+	* Thuban/UI/mainwindow.py (MainWindow.LayerShowTable): Prefix the
+	table window with 'Layer Table:' instead of 'Table:'.
+
+2003-05-23  Jan-Oliver Wagner <jan at intevation.de>
+
+	Give all tables a title via mix-in TitledObject.LayerShowTable
+
+	* Thuban/Model/base.py (TitledObject.SetTitle): Call method 'issue'
+	only if it exists.
+
+	* Thuban/Model/table.py (DBFTable, MemoryTable): mix-in TitledObject
+	and call its init-method with a default title. Remove Title() method.
+
+	* Thuban/Model/transientdb.py (TransientTable, TransientJoinedTable,
+	AutoTransientTable): mix-in TitledObject and call its init-method with
+	a default title. Remove Title() method.
+
+2003-05-23  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/session.py (Session.AddShapeStore): Define
+	AddShapeStore analogously to AddTable.
+
+	* test/test_session.py (TestSessionSimple.test_add_shapestore):
+	New. Test for AddShapeStore
+
+2003-05-23  Jan-Oliver Wagner <jan at intevation.de>
+
+	Introducing QueryTableFrame and a very coarse ShowTable implementation.
+
+	* Thuban/UI/tableview.py (LayerTableFrame, QueryTableFrame): Split the
+	class LayerTableFrame into two classes, LayerTableFrame and QueryTableFrame.
+	The latter implements the selection GUI without dependency on a layer.
+	LayerTableFrame now is derived from QueryTableFrame and connects
+	to a layer.
+
+	* Thuban/UI/mainwindow.py (MainWindow.TableShow): A very coarse
+	implementation that still needs work.
+
+	* Thuban/Model/layer.py (Layer.TreeInfo): Added filename.
+
+2003-05-22  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/Model/transientdb.py (TransientJoinedTable.__init__): 
+	Added "outer_join = False" as optional parameter.
+	(TransientJoinedTable.create): If outer join is true, perform a
+	"LEFT OUTER JOIN" instead of "JOIN", which preserves all records of
+	the left table. Records not matching are filled with 0 / None.
+
+	* Thuban/UI/join.py (JoinDialog.__init__): Checkbox for outer join.
+	(JoinDialog.OnJoin): Consider outer join check box.
+
+2003-05-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/join.py (JoinDialog.OnJoin): Use exc_info in a
+	somewhat safer way. Storing the traceback in a local variable can
+	lead to memory leaks
+
+2003-05-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/join.py (JoinDialog.OnJoin): Make sure to really call
+	the wxMessageDialog's Destroy() method.
+
+2003-05-22  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/UI/join.py (JoinDialog.__init__): Make use of 
+	TransientTable.Title()
+
+2003-05-22  Frank Koormann  <frank.koormann at intevation.de>
+
+	Join Dialog, initial version.
+
+	* Thuban/UI/mainwindow.py (MainWindow.TableJoin): Removed print.
+
+	* Thuban/UI/join.py (JoinDialog): Functional implementation of 
+	former framework. Renamed Table1/Table2 to LeftTable/RightTable
+	in all occurences.
+
+	* Thuban/Model/transientdb.py (TransientJoinedTable.__doc__): 
+	Typo fixed.
+
+2003-05-22  Bernhard Herzog  <bh at intevation.de>
+
+	Give the tables titles so that the GUI can display more meaningful
+	names. For now the titles are fixed but depend on e.g. filenames
+	or the titles of the joined tables.
+
+	* Thuban/Model/transientdb.py (TransientTable.Title)
+	(TransientJoinedTable.Title, AutoTransientTable.Title): New.
+
+	* Thuban/Model/table.py (DBFTable.Title, MemoryTable.Title): New.
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_auto_transient_table_title): New. Test
+	for the Title method
+	(TestTransientTable.test_transient_joined_table)
+	(TestTransientTable.test_transient_table): Add test for the Title
+	methods
+
+	* test/test_memory_table.py (TestMemoryTable.test_title): New.
+	Test for the Title method
+
+	* test/test_dbf_table.py (TestDBFTable.test_title): New. Test for
+	the Title method
+
+2003-05-22  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_layer.py (TestLayer.setUp, TestLayer.tearDown):
+	Provide a better way to destroy the layers
+	(TestLayer.test_base_layer, TestLayer.test_arc_layer)
+	(TestLayer.test_point_layer, TestLayer.test_empty_layer)
+	(TestLayer.test_polygon_layer, TestLayer.test_get_field_type): Use
+	the new way to destroy the layers.
+	(TestLayer.test_derived_store): New. Test for using a layer with a
+	DerivedShapeStore
+
+	* Thuban/Model/layer.py (Layer.SetShapeStore): Only set the
+	filename if the shape store actually has one.
+
+2003-05-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/table.py (DBFTable.FileName): New. Accessor method
+	for the filename
+
+	* test/test_dbf_table.py (TestDBFTable.test_filename): New. Test
+	for the FileName method
+	(TestDBFTableWriting.test_write): Fix spelling of filename
+
+2003-05-22  Thomas Koester  <tkoester at intevation.de>
+
+	* Thuban/Model/range.py, test/test_range.py: Brought over new Range
+	from SciParam that now really is immutable.
+
+2003-05-22  Frank Koormann  <frank.koormann at intevation.de>
+
+	Layer Top/Bottom placement added to legend.
+
+	* Thuban/UI/legend.py 
+	(LegendPanel._OnMoveTop(), LayerPanel._OnMoveBottom): New, methods
+	bound to tool events.
+	(LegendTree.MoveCurrentItemTop(), LegendTree.MoveCurrentItemBottom):
+	New, methods binding the event methods with the map methods.
+
+	* Thuban/Model/map.py (Map.TopLayer(), Map.BottomLayer()): New, place 
+	layer at top/bottom of layer stack.
+
+	* Resources/Bitmaps/top_layer.xpm: New button icon.
+
+	* Resources/Bitmaps/bottom_layer.xpm: New button icon.
+
+2003-05-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/session.py (Session.RemoveTable): New method to
+	remove tables
+
+	* test/test_session.py (TestSessionSimple.test_remove_table): New.
+	Test for RemoveTable
+
+2003-05-22  Thomas Koester  <tkoester at intevation.de>
+
+	* Thuban/Model/classgen.py: Added short module doc string and CVS id.
+	(ClassGenerator.GenUniformDistribution): Use new Range __init__, too.
+
+2003-05-22  Bernhard Herzog  <bh at intevation.de>
+
+	Implement a way to discover dependencies between tables and
+	shapestores.
+
+	* Thuban/Model/transientdb.py (TransientTableBase.Dependencies)
+	(TransientJoinedTable.Dependencies)
+	(AutoTransientTable.SimpleQuery): New. Implement the dependencies
+	interface
+	(TransientJoinedTable.__init__): Keep tack of the original table
+	objects in addition to the corresponding transient tables.
+
+	* Thuban/Model/table.py (DBFTable.Dependencies)
+	(MemoryTable.Dependencies): New. Implement the dependencies
+	interface
+
+	* Thuban/Model/data.py (ShapeTable): New. Helper class for
+	ShapefileStore
+	(ShapefileStore.__init__): Use ShapeTable instead of
+	AutoTransientTable
+	(ShapefileStore.Table, ShapefileStore.Shapefile): Add doc-strings
+	(ShapefileStore.FileName, ShapefileStore.FileType): New. Accessor
+	methods for filename and type
+	(ShapefileStore.Dependencies): New. Implement the dependencies
+	interface
+	(DerivedShapeStore): New class to replace SimpleStore. The main
+	difference to SimpleStore is that it depends not on a shapefile
+	but another shapestore which expresses the dependencies a bit
+	better
+	(SimpleStore.__init__): Add deprecation warning.
+
+	* test/test_dbf_table.py (TestDBFTable.test_dependencies): New.
+	Test for the Dependencies method.
+
+	* test/test_memory_table.py (TestMemoryTable.test_dependencies):
+	New. Test for the Dependencies method.
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_auto_transient_table_dependencies): New.
+	Test for the Dependencies method.
+	(TestTransientTable.test_transient_joined_table): Add test for the
+	Dependencies method.
+
+	* test/test_session.py (TestSessionSimple.setUp)
+	(TestSessionSimple.tearDown): New. Implement a better way to
+	destroy the sessions.
+	(TestSessionSimple.test_initial_state)
+	(TestSessionSimple.test_add_table): Bind session to self.session
+	so that it's destroyed by tearDown
+	(TestSessionSimple.test_open_shapefile): New. Test for
+	OpenShapefile and the object it returns
+
+2003-05-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/session.py (Session.AddTable): New method to
+	register tables with the session.
+	(Session.Tables): Return the tables registered with AddTable too.
+
+	* test/test_session.py (TestSessionSimple.test_add_table): New.
+	Test case for the AddTable method
+
+2003-05-22  Frank Koormann  <frank.koormann at intevation.de>
+
+	UI polishing updates: Place main buttons (OK, Cancel, etc) in the 
+	lower right corner, center labels for selections, initialize controls
+	in reasonable order for keyboard navigation. 
+
+	* Thuban/UI/projdialog.py (ProjFrame.__init__, ProjFrame.__doLayout)
+	(ProjFrame.__DoOnProjAvail): Determine position of current projection
+	using the wxListBox.FindString() method. Still a problem (#1886)
+
+	* Thuban/UI/classifier.py 
+	(Classifier.__init__, SelectPropertiesDialog.__init__)
+
+	* Thuban/UI/classgen.py (ClassGenDialog.__init__, 
+	(ClassGenDialog.__DoOnGenTypeSelect): Moved initialization of the 
+	different classification types from here to __init__.
+	(GenUniquePanel.__init__): Set the column width of the first field 
+	in the Field ListCtrl to the full width.
+ 
+	* Thuban/UI/tableview.py (LayerTableFrame.__init__): Rename 'Save As'
+	Button to 'Export'. Center Buttons in Selection Box, set Focus to
+	Grid. 
+	(LayerTableFrame.OnKeyDown()): New, bound to the grid with EVT_KEY_DOWN,
+	changes focus to the Selection when pressing "Alt-S".
+
+	* Thuban/UI/legend.py (LegendTree.__SetVisibilityStyle): Only gray out
+	the text if not visible. The italic font sometimes exceeds the
+	rendering area.
+
+2003-05-21  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/dock.py (DockFrame): Rename references to _OnClose
+	to OnClose so that Thuban closes correctly.
+
+	* Thuban/UI/mainwindow.py (MainWindow.OnClose): Call
+	DockFrame.OnClose, not DockFrame._OnClose.
+
+2003-05-21  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classgen.py (ClassGenerator.GenQuantiles): Remove
+	references to 'inf' and use new Range __init__ to pass floats
+	directly rather than converting them to strings first. 
+	Fixes RTBug #1876.
+
+	* Thuban/Model/classification.py (ClassGroupRange.SetRange):
+	Use new Range ___init__ to pass floats.
+
+	* Thuban/Model/layer.py (RasterLayer.__init__): Test if the
+	filename is a valid image file. Throw IOError otherwise.
+
+	* Thuban/Model/range.py: Brought over new Range from SciParam that
+	is immutable and has an __init__ which can accept floats.
+
+	* Thuban/UI/mainwindow.py (MainWindow.AddLayer): Move OpenShapefile
+	into try block. AddLayer doesn't throw any exceptions anymore. 
+	(MainWindow.AddRasterLayer): Move constructor of RasterLayer into 
+	try block.
+
+	* Thuban/UI/projdialog.py (GeoPanel.__init__): Put Degrees as
+	the first item in choices. Fixes RTBug #1882.
+
+	* Thuban/UI/renderer.py (MapRenderer.render_map): Check if scale
+	has gone to 0 which is a serious problem. abort.
+	(MapRenderer.draw_raster_layer): Catch IOError seperately and
+	print the error from GDAL.
+
+	* Thuban/UI/tableview.py (TableGrid.__init__): Call
+	ToggleEventListeners to turn on listening. 
+	(TableGrid.ToggleEventListeners): New. Turns event listening on
+	and off so as to prevent excessive messages.
+	(LayerTableFrame.OnQuery): Use TableGrid.ToggleEventListeners
+	to suppress excessive messages when selecting many rows. 
+	Fixes RTBug #1880.
+
+	* Thuban/UI/view.py: Added checks against if scale == 0. This
+	is a serious problem that can occur when an image without 
+	geo data is loading and causes the map projection bounds to
+	go to infinity. Right now, the solution is to simply try
+	to recover.
+
+	* extensions/thuban/cpl_mfile.cpp (MFILEClose): Make sure
+	to set the MFILEReceiver attributes even if the data is NULL.
+
+	* extensions/thuban/gdalwarp.cpp: Improved the error handling
+	and passed GDAL messages back up to the Python layer. Also
+	tried to fix some memory leaks that were present in the original
+	utility but didn't matter because the program aborted.
+
+	* test/test_range.py: Copied over tests from SciParam. Removed
+	tests against importing. Fixes RTBug #1867.
+
+2003-05-21  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_load.py: Remove unused imports and restructure the
+	test code
+	(LoadSessionTest): Split into one class for each test and turn
+	LoadSessionTest itself into the base class for all such session
+	tests.
+	(ClassificationTest): New base class for load tests that test
+	classifications
+	(TestSingleLayer, TestLayerVisibility, TestClassification)
+	(TestLabels, TestLayerProjection, TestRasterLayer): New classes
+	for the individual tests
+
+	* test/support.py (FileLoadTestCase.filename): New base class for
+	file loading tests
+
+2003-05-21  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Resources/Projections/defaults.proj: Renamed 'Universal Transverse
+	Mercator' to 'UTM Zone 32' as a more convenient example.
+	Added 'Gauss Krueger Zone 6'.
+
+	* Data/iceland_sample_raster.thuban: political polygon now
+	filled transparent to have the raster image visible at once.
+
+2003-05-21  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow): Renamed _OnClose() back to 
+	OnClose() to keep in sync with extensions. Internally Thuban
+	still uses "underscored" names.
+
+2003-05-20  Jonathan Coles   <jonathan at intevation.de>
+
+	This puts back Raster layer support. These layers support projections
+	through the GDAL library. Currently, the CVS version is being used.
+	There are no Debian packages available although this may change soon. 
+	A GDAL driver was extended to support writing to memory rather to
+	files.
+
+	There is still some work that needs to be done, such as some error
+	handling when loading invalid images or when there is a problem
+	projecting the image. This putback simply checks in the majority
+	of the work.
+
+	* setup.py: Add gdalwarp library extension.
+
+	* Thuban/Model/layer.py (BaseLayer.HasClassification): New.
+	Defaults to False, but can be overridden by subclasses if they
+	support classification.
+	(RasterLayer): New. Defines a new layer that represents an
+	image.
+
+	* Thuban/Model/load.py (SessionLoader.__init__): Add rasterlayer
+	tag handler.
+	(SessionLoader.start_layer): Encode the filename.
+	(SessionLoader.start_rasterlayer, SessionLoader.end_rasterlayer):
+	New. Supports reading a rasterlayer tag.
+
+	* Thuban/Model/map.py (Map.BoundingBox): Fix typo in comment.
+
+	* Thuban/Model/save.py (XMLWriter.encode): Don't assume that we
+	get a string in Latin1. If we get such as string convert it to
+	unicode first, otherwise leave if alone before encoding.
+	(SessionSaver.write_layer): Add support for writing both Layers
+	and RasterLayers.
+
+	* Thuban/Model/transientdb.py (AutoTransientTable.SimpleQuery): 
+	The right argument may not be a string, it could also be a Column.
+
+	* Thuban/UI/application.py (ThubanApplication.CreateMainWindow):
+	Make initial window size 600x400. Fixes RTBug #1872.
+
+	* Thuban/UI/classifier.py (Classifier.__init__): Rearrange how
+	the dialog is constructed so that we can support layers that
+	do not have classifications.
+	(Classifier._OnTry): Only build a classification if the layer
+	supports one.
+
+	* Thuban/UI/legend.py: Change all checks that a layer is an
+	instance of Layer into checks against BaseLayer.
+	(LegendTree.__FillTreeLayer): Only add children to a branch if
+	the layer supports classification.
+
+	* Thuban/UI/mainwindow.py (MainWindow.NewSession,
+	MainWindow.OpenSession): Don't proceed with an action if the 
+	user chooses Cancel when they are asked to save changes.
+	(MainWindow.AddRasterLayer): New. Open a dialog to allow the
+	user to select an image file. Create a new RasterLayer and add
+	it to the map.
+
+	* Thuban/UI/renderer.py (MapRenderer.render_map): Add support
+	for rendering RasterLayer layers.
+	(MapRenderer.draw_raster_layer): Actually method that calls
+	the GDALWarp python wrapper and constructs an image from the
+	data returned.
+
+	* Thuban/UI/tableview.py (LayerTableFrame.__init__): Change the
+	Choices symbols to match those used in the table query method.
+	Replace deprecated method calls on table with new method names.
+
+	* Thuban/UI/view.py (MapCanvas.set_view_transform): Try to limit
+	how small the scale can get. This still needs more testing.
+
+	* extensions/thuban/bmpdataset.cpp: New, but copied from GDAL.
+	Provides a driver to output in .bmp format.
+
+	* extensions/thuban/cpl_mfile.cpp, extensions/thuban/cpl_mfile.h: 
+	New. Provides IO routines which write to memory, rather than a file.
+
+	* extensions/thuban/gdalwarp.cpp: New, but basically a direct copy
+	of the gdalwarp utility provided in GDAL. Added function calls
+	that can be accessed from python.
+
+	* Data/iceland_sample_raster.thuban: New. Sample file that uses
+	a raster layer.
+
+	* Data/iceland/island.tfw, Data/iceland/island.tif: New. Raster
+	layer image data.
+
+	* Doc/thuban.dtd: Added rasterlayer attribute definition.
+
+	* test/test_layer.py, test/test_load.py, test/test_save.py: Added
+	tests associated with the raster layer code.
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_auto_transient_table_query): Added a test 
+	for using a Column object as the "right" parameter to a query.
+
+2003-05-19  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Thuban/version.py (get_changelog_date): 
+	Catch exceptions if ChangeLog does not exist.
+
+	* Thuban/UI/view.py (MapCanvas.Export): Bugfix
+
+2003-05-19  Frank Koormann  <frank.koormann at intevation.de>
+
+	Extended version information for Thuban
+
+	* Thuban/version.py: New, version information for Thuban: Last
+	modification date and last ChangeLog entry date.
+
+	* Thuban/UI/mainwindow.py (MainWindow.About()): Extended version
+	information: Display Thuban, wxPython and Python version.
+
+2003-05-16  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/save.py: Remove some unused imports including the
+	__future__ import for nested_scopes as Thuban relies on Python 2.2
+	now.
+	(XMLWriter.encode): Remove the special case for a None argument.
+	In the saver encode is always called with a string argument.
+
+2003-05-16  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/__init__.py: Remove the work-around for the locale bug
+	in wxPython (at least when usinvg wxGTK) prior to 2.4. The symptom
+	of the bug was that e.g. float("1.2") would fail. Thuban now
+	requires 2.4.x.
+	
+2003-05-16  Frank Koormann   <frank.koormann at intevation.de>
+
+	Printing enhancement and WMF export (under Win32)
+
+	* Thuban/UI/renderer.py (ExportRenderer): New, derived from
+	ScreenRenderer. Renders Map, Legend and Scalebar for export.
+	(PrinterRenderer): New, derived from ExportRenderer. Replaces the old 
+	PrintRender.
+
+	* Thuban/UI/view.py (MapPrintout.__init__): Enhanced parameter set
+	to fullfil information needed for PrinterRenderer.
+	(MapCanvas.Export): New. Export Map (currently only to WMF on Win32).
+	(MapCanvas.Print): Adapted to new MapPrintout.
+	(OutputTransform): General calculations to transform from canvas
+	coordinates to export/printing devices.
+
+	* Thuban/UI/mainwindow.py (MainWindow.ExportMap()): New. Added also 
+	new method_command to call ExportMap, with platform dependency (only
+	__WXMSW__)
+  
+	* Thuban/UI/scalebar.py (ScaleBar.DrawScaleBar): Position and Size
+	of scalebar drawing area as new parameters.
+	
+	* Thuban/Model/scalebar.py (roundInterval): round long instead of int
+
+	* Thuban/UI/legend.py (ScalebarBitmap.__SetScale): 
+	Update to extended scalebar.DrawScalebar header.
+
+	* test/test_export.py: New, test Thuban.UI.view.OutputTransform()
+
+	* test/test_scalebar.py: Made test executable as standalone.
+
+2003-05-16  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/table.py (Table): Remove this compatibility alias
+	for DBFTable.
+
+	* test/test_table.py: Import DBFTable as Table because that alias
+	doesn't exist anymore.
+
+	* Thuban/UI/classgen.py: Remove some unused imports
+
+2003-05-14  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classgen.py (ClassGenerator.GenSingletonsFromList):
+	Fix docstring.
+	(ClassGenerator.GenUniformDistribution): Fix spelling of method name.
+	(ClassGenerator.GenQuantiles): Use the left/right brackets and min/max
+	values of the supplied range to determine the beginning and end
+	bounds of the generated classes.
+
+	* Thuban/Model/range.py (Range.number_re): Now accepts floats that
+	do not have a leading 0 (.5 is now accepted as well as 0.5).
+
+	* Thuban/UI/classgen.py (ClassGenDialog.OnOK): Fix name of method
+	call to ClassGenerator.GenUniformDistribution.
+
+	* Thuban/UI/projdialog.py (ProjFrame.__do_layout): Fix Windows 
+	layout bug with the 'Projection' label.
+
+	* test/support.py (FloatTestCase): New. Needed for the Range tests.
+
+	* test/test_range.py: New. Imported from SciParam.
+
+2003-05-12  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classgen.py (GenQuantilesPanel.GetList): Replace call
+	to table.UniqueValues() with calls that retrieve all the values
+	from the table. This will need to be replaced by a method on table
+	which can simply return the list (perhaps more efficiently).
+
+2003-05-12  Jonathan Coles   <jonathan at intevation.de>
+
+	The return value of ClassGenerator.CalculateQuantiles has changed.
+	Refer to the documentation for details.
+
+	* test/test_classgen.py: Modified Quantile tests to use the
+	new return values.
+
+	* Thuban/Model/classgen.py 
+	(ClassGenerator.GenQuantiles): Add comments describing the parameters,
+	use new return values from CalculateQuantiles to produce the correct 
+	range bounds in the Classification.
+	(ClassGenerator.CalculateQuantiles): Add more comments describing
+	the return values and parameters. Make minor adjustments to improve
+	the legibility of the code. Fix problem with adjusted not being set
+	in most cases.
+
+2003-05-12  Frank Koormann <frank.koormann at intevation.de>
+	
+	* Thuban/Model/save.py (XMLWriter.encode()): Explicite call to unicode 
+	and latin1. Fixes #1851 finally.
+
+2003-05-09  Jonathan Coles   <jonathan at intevation.de>
+
+	* test/test_classgen.py: New. Tests the Quantile algorithm.
+
+	* Thuban/Model/classgen.py (ClassGenerator.CalculateQuantiles):
+	Clean up debugging statement, add comments, fix a small bug in the
+	returned adjusted percentiles.
+	
+2003-05-09  Jonathan Coles   <jonathan at intevation.de>
+
+	Introduces Range class from SciParam into the ClassGroupRange class,
+	and such ranges can now be saved and loaded from disk.
+
+	Quantiles are now available in the Classification Generator.
+
+	Initial support for building Queries on a table. Doesn't do anything
+	but run some tests.
+
+	* Thuban/Model/classification.py: Explicit imports.
+	(ClassGroupRange): Use the Range class to store the underlying
+	range information. The interface remains the same, except for
+	GetRange(), and you can also supply a Range object as the min 
+	parameter to SetRange or __init__.
+
+	* Thuban/Model/load.py (XMLReader.encode): New. Encodes the given
+	string appropriately for use in Thuban. Fixes RTbug #1851.
+	(SessionLoader.end_projection): Handle the context of the
+	projection tag a bit better by looking at what objects are not
+	None. There was an assumption that a projection tag for a map
+	could occur before any layers.
+	(SessionLoader.start_clrange): Provide backward compatibility for
+	reading min/max values as well as the new range parameter.
+
+	* Thuban/Model/map.py: Explicit imports.
+
+	* Thuban/Model/resource.py: Import _.
+	(ProjFileSaver.write): write header using projfile.dtd.
+
+	* Thuban/Model/save.py: Explicit imports.
+	(XMLWriter.encode): New. Encode the given string from a format
+	used by Thuban into UTF-8. Fixes RTbug #1851.
+
+	* Thuban/UI/classgen.py: Explicit imports.
+	(ClassGenDialog.__init__): Clean up the code and add support
+	for Quantiles.
+	(ClassGenDialog.OnOK): Add support for Quantiles.
+	(GenQuantilesPanel): New. Input panel for Quantiles.
+	(ClassGenerator, CustomRamp, MonochromaticRamp, GreyRamp, RedRamp,
+	GreenRamp, BlueRamp, HotToColdRamp): Move to Thuban/Model/classgen.py
+
+	* Thuban/Model/classgen.py: New. Contains all the classes named above.
+
+	* Thuban/UI/classifier.py: Explicit imports.
+	(ClassTable.GetValueAsCust, ClassTable.__ParseInput, 
+	ClassTable.SetValueAsCustom): Reworked to use new Range class.
+
+	* Thuban/UI/legend.py: Explicit imports.
+
+	* Thuban/UI/mainwindow.py: Add support for the Join Dialog. Added
+	a Table menu and associated method calls.
+	(MainWindow.choose_color): Removed. No longer needed.
+
+	* Thuban/UI/projdialog.py (ProjFrame.__VerifyButtons): Save button
+	should be disabled if no projection is selected in the available
+	list.
+
+	* Thuban/UI/renderer.py: Explicit imports.
+
+	* Thuban/UI/tableview.py (TableGrid.OnRangeSelect): Fix some issues
+	with correctly selecting the rows and issuing the right events.
+	Be sure to call Skip() to allow the grid to do some of its own
+	handling which allows the rows to actually be selected.
+	(LayerTableGrid.select_shapes): Rename from select_shape. Supports
+	selecting multiple shapes.
+	(LayerTableFrame): Support for building Queries.
+	(LayerTableFrame.select_shapes): Allow multiple shapes to be selected.
+
+	* Thuban/UI/tree.py: Explicit imports.
+
+	* Thuban/UI/view.py (MapCanvas): Delegate "SelectedShapes" so the
+	table view can call it.
+
+	* test/test_classification.py: Explicit imports.
+	(TestClassification.test_ClassGroupRange): Fix test for new
+	Range class.
+
+	* Doc/thuban.dtd: Add range parameter for clrange.
+
+	* Thuban/Model/range.py: Taken from SciParam. Used as the underlying
+	object in ClassGroupRange, and also uesd for inputting ranges in
+	the classifer table and elsewhere.
+
+	* Thuban/UI/join.py: New. Initial Join dialog. No real functionality
+	yet.
+
+2003-05-09  Frank Koormann <frank.koormann at intevation.de>
+
+	* Thuban/UI/scalebar.py (DrawScaleBar): Draw only if interval > 0.0.
+
+2003-05-08  Frank Koormann <frank.koormann at intevation.de>
+
+	Coding style updates
+
+	* test/test_scalebar.py: Replaced tab indentation by spaces.
+
+	* Thuban/UI/scalebar.py: Explicit imports.
+
+2003-05-08  Frank Koormann <frank.koormann at intevation.de>
+
+	* Thuban/UI/scalebar.py 
+	(ScaleBar.DrawScalebar): Format string bug fixed.
+
+2003-05-08  Frank Koormann <frank.koormann at intevation.de>
+
+	Reorganization of scalebar component (no wx in Thuban/Model)
+
+	* Thuban/Model/scalebar.py: Rendering moved to Thuban/UI/scalebar.py 
+	(deriveInterval): 
+	Calculate scalebar interval and unit which fits in width for scale.
+	(roundInterval): Round float.
+
+	* Thuban/UI/scalebar.py (ScaleBar): Scalebar rendering
+
+	* test/test_scalebar.py: Test for Thuban/Model/scalebar.py methods.
+
+	* Thuban/UI/legend.py: Import Thuban.UI.scalebar
+
+2003-05-08  Frank Koormann <frank.koormann at intevation.de>
+
+	* Thuban/UI/legend.py (ScalebarBitmap.SetCanvas): 
+	Initialize ScaleBar with canvas.map
+
+	* Thuban/Model/scalebar.py (ScaleBar.roundInterval()): New, 
+	round intervals to display smarter lengths
+	(ScaleBar.DrawScalebar): Draw Scalebar only if the map contains a 
+	layer. If the maps has no projection applied grey the scalebar.
+
+2003-05-07  Frank Koormann <frank.koormann at intevation.de>
+	
+	Basic Scalebar features added.
+
+	* Thuban/Model/scalebar.py (ScaleBar): New, scalebar rendering.
+
+	* Thuban/UI/legend.py (LegendPanel): Added scalebar bitmap
+	(ScaleBarBitmap): New, links the scalebar bitmap with view messages
+	and the renderer.
+
+	* Thuban/UI/view.py (MapCanvas.set_view_transform): Issue SCALE_CHANGED.
+
+	* Thuban/UI/messages.py: SCALE_CHANGED added.
+
+2003-05-07  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/session.py (Session.__init__): New instance
+	variable shapestores to hold a list of all open shapestore objects
+	(Session.ShapeStores): New. Accessor method for the shapestores
+	list.
+	(Session._add_shapestore, Session._clean_weak_store_refs): New.
+	Internal methods to maintain the shapestores list.
+	(Session.Tables): New. Return all tables open in the session.
+	(Session.OpenShapefile): Insert the new ShapeStore into the
+	shapestores list.
+
+	* test/test_session.py (TestSessionSimple.test_initial_state): Add
+	tests for ShapeStores and Tables
+	(TestSessionWithContent.test_shape_stores)
+	(TestSessionWithContent.test_tables): New. Test cases for
+	ShapeStores and Tables
+
+2003-05-07  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/transientdb.py (TransientTableBase.ReadRowAsDict):
+	Add comments about the optimizations used.
+	(AutoTransientTable.ReadValue, TransientTableBase.ReadValue): New.
+	Implement the ReadValue table interface method.
+
+	* test/test_transientdb.py
+	(TestTransientTable.run_iceland_political_tests)
+	(TestTransientTable.test_transient_joined_table): Add tests for
+	ReadValue
+
+2003-05-07  Frank Koormann <frank.koormann at intevation.de>
+
+	* Resources/Bitmaps/fulllayerextent.xpm,
+	Resources/Bitmaps/fullselextent.xpm: Replaced the place holders with
+	new icons.
+ 
+2003-05-06  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/transientdb.py (AutoTransientTable.SimpleQuery):
+	New. Simply delegate to the transient table's version.
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_auto_transient_table_query): New. Test
+	case for AutoTransientTable's SimpleQuery
+
+2003-05-06  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/transientdb.py (TransientTableBase.SimpleQuery):
+	Implement a simple query method for the query dialog
+	(TransientTableBase.create): Add an INTEGER PRIMARY KEY that holds
+	the row index or shapeid.
+	(TransientTable.create): Insert the right value of the row index
+	(TransientJoinedTable.create): Copy the row index of the left
+	table to the joined result table
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_transient_table_read_twice): Fix
+	doc-string
+	(TestTransientTable.test_transient_table_query): New. Test for the
+	SimpleQuery method
+
+2003-05-06  Bernhard Herzog  <bh at intevation.de>
+
+	Convert all table users to use the new table interface. This only
+	covers Thuban itself, not GREAT-ER or other applications built on
+	Thuban yet, so the compatibility interface stays in place for the
+	time being but it now issues DeprecationWarnings.
+
+	Finally, the new Table interface has a new method, HasColumn.
+
+	* Thuban/Model/table.py (OldTableInterfaceMixin): All methods
+	issue deprecation warnings when they're. The warnings refer to the
+	caller of the method.
+	(OldTableInterfaceMixin.__deprecation_warning): New. Helper method
+	for the deprecation warnings
+
+	* test/test_table.py: Ignore the deprecation warnings for the old
+	table in the tests in this module. The purpose of the tests is to
+	test the old interface, after all.
+
+	* test/test_transientdb.py
+	(TestTransientTable.run_iceland_political_tests): Use the
+	constants for the types. Add a test for HasColumn
+	(TestTransientTable.test_transient_joined_table): Adapt to new
+	table interface. Add a test for HasColumn
+	(TestTransientTable.test_transient_table_read_twice): Adapt to new
+	table interface
+
+	* Thuban/UI/tableview.py (DataTable.SetTable, DataTable.GetValue):
+	Adapt to new table interface
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Adapt to
+	new table interface
+
+	* Thuban/UI/controls.py (RecordListCtrl.fill_list)
+	(RecordTable.SetTable): Adapt to new table interface
+
+	* Thuban/UI/classifier.py (Classifier.__init__)
+	(Classifier.__init__): Adapt to new table interface
+
+	* Thuban/UI/classgen.py (ClassGenDialog.__init__)
+	(GenUniformPanel._OnRetrieve, GenUniquePanel._OnRetrieve): Adapt
+	to new table interface
+
+	* Thuban/Model/transientdb.py (TransientTableBase.HasColumn)
+	(AutoTransientTable.HasColumn): Implement the new table interface
+	method
+	(AutoTransientTable.ReadRowAsDict, AutoTransientTable.ValueRange)
+	(AutoTransientTable.UniqueValues): Adapt to new table interface
+
+	* Thuban/Model/layer.py (Layer.SetShapeStore, Layer.GetFieldType):
+	Adapt to new table interface
+
+	* test/test_layer.py (TestLayer.open_shapefile): Helper method to
+	simplify opening shapefiles a bit easier.
+	(TestLayer.test_arc_layer, TestLayer.test_polygon_layer)
+	(TestLayer.test_point_layer): Use the new helper method
+	(TestLayer.test_get_field_type): New. Test for the GetFieldType
+	method
+
+	* test/test_dbf_table.py (TestDBFTable.test_has_column): Test for
+	the new table method
+
+	* test/test_memory_table.py (TestMemoryTable.test_has_column):
+	Test for the new table method HasColumn
+
+2003-05-06  Jonathan Coles   <jonathan at intevation.de>
+
+	Addresses the "Selection Extent" wish of RTbug #1787.
+
+	* Resources/Bitmaps/fulllayerextent.xpm,
+	Resources/Bitmaps/fullselextent.xpm: Bitmaps for layer and selection
+	extent. These are just place holders for the real bitmaps.
+
+	* Thuban/Model/layer.py (Shape): Since a Shape is immutable only
+	calculate the bounding box once (the first time compute_bbox() is 
+	called).
+	(Layer.ShapesBoundingBox): New. Given a list of shape ids, return
+	the bounding box for the shapes in lat/long coordinates. 
+
+	* Thuban/UI/mainwindow.py: Added new "Full selection extent" menu
+	option.
+	(MainWindow.has_selected_shapes): New. Returns true if there are 
+	any selected shapes.
+	(MainWindow.FullSelectionExtent): New. Calls 
+	MapCanvas.FitSelectedToWindow() when the user selects the menu option.
+	(_has_selected_shapes): New. Returns true if there are any 
+	selected shapes.
+
+	* Thuban/UI/selection.py (Selection.HasSelectedShapes): New. Returns
+	true if there are any selected shapes.
+
+	* Thuban/UI/view.py (MapCanvas): Added delegated method
+	HasSelectedShapes.
+	(MapCanvas.FitSelectedToWindow): New. Centers and scales any selected
+	shapes on the canvas using the map projection (if any).
+
+	* test/test_layer.py (TestLayer.test_arc_layer): Add some tests
+	for Layer.ShapesBoundingBox().
+
+2003-05-06  Bernhard Herzog  <bh at intevation.de>
+
+	* Resources/Projections/defaults.proj: Fix spelling of Mercator
+
+2003-05-05  Jonathan Coles   <jonathan at intevation.de>
+
+	Addresses the "Full Layer Extent" wish of RTbug #1787.
+
+	* Resources/Projections/defaults.proj: Added UK National Grid.
+
+	* Thuban/UI/mainwindow.py: Added new "Full layer extent" menu option.
+	(MainWindow.FullLayerExtent): New. Calls MapCanvas.FitLayerToWindow()
+	when the user selects the menu option.
+
+	* Thuban/UI/view.py (MapCanvas.FitLayerToWindow): New. Centers and
+	scales the given layer on the canvas using the map projection.
+
+2003-05-05  Bernhard Herzog  <bh at intevation.de>
+
+	Convert the table implementations to a new table interface. All
+	tables use a common mixin class to provide backwards compatibility
+	until all table users have been updated.
+
+	* Thuban/Model/table.py (OldTableInterfaceMixin): Mixin class to
+	provide backwards compatibility for table classes implementing the
+	new interface
+	(DBFTable, MemoryTable): Implement the new table interface. Use
+	OldTableInterfaceMixin as base for compatibility
+	(DBFColumn, MemoryColumn): New. Column description for DBFTable
+	and MemoryTable resp.
+
+	* test/test_dbf_table.py: New. Test cases for the DBFTable with
+	the new table interface.
+
+	* test/test_memory_table.py: New. Test cases for the MemoryTable
+	with the new table interface.
+
+	* test/test_table.py: Document the all tests in this file as only
+	for backwards compatibility. The equivalent tests for the new
+	interface are in test_memory_table.py and test_dbf_table.py
+	(MemoryTableTest.test_read): field_info should be returning tuples
+	with four items
+	(MemoryTableTest.test_write): Make doc-string a more precise.
+
+	* Thuban/Model/transientdb.py (TransientTableBase): Convert to new
+	table interface. Derive from from OldTableInterfaceMixin for
+	compatibility.
+	(TransientTableBase.create): New intance variable column_map to
+	map from names and indices to column objects
+	(TransientTable.create): Use the new table interface of the input
+	table
+	(AutoTransientTable): Convert to new table interface. Derive from
+	from OldTableInterfaceMixin for compatibility.
+	(AutoTransientTable.write_record): Removed. It's not implemented
+	yet and we still have to decide how to handle writing with the new
+	table and data framework.
+
+	* test/test_transientdb.py
+	(TestTransientTable.run_iceland_political_tests)
+	(TestTransientTable.test_transient_joined_table): Use the new
+	table interface
+
+2003-05-05  Jonathan Coles   <jonathan at intevation.de>
+
+	This is namely a collection of UI updates to improve user interactivity.
+	Tabbing between controls now exists and you can use ESC to close dialog
+	boxes; ENTER will active the default button.
+
+	* Thuban/UI/classgen.py (ClassGenDialog.__init__): Rearrange the
+	order that the controls are created so that tabbing works correctly. 
+	(ClassGenDialog.OnOK): Renamed from _OnGenerate() so that the 
+	wxDialog can handle the default button correctly.
+	(ClassGenDialog.OnCancel): Renamed from _OnCloseBtn() for the
+	same reasons as for OnOK.
+	(GenUniformPanel._OnRetrieve): Call wxBeginBusyCursor/wxEndBusyCursor
+	when we ask the table for the maximum/minimum values of a field
+	which could take a very long time.
+
+	* Thuban/UI/classifier.py (Classifier.__init__): Rearrange the
+	order that the controls are created so that tabbing works correctly.
+	(SelectPropertiesDialog.__init__): Rearrange the order that the 
+	controls are created so that tabbing works correctly.
+
+	* Thuban/UI/dialogs.py: Copied NonModalDialog box and changed it
+	to derive from a wxDialog but behave like the original implementation
+	which was derived from a wxFrame. wxDialog provides useful key
+	handling functionality like ESC calling OnCancel and ENTER calling
+	OnOK which is lost with wxFrame.
+
+	* Thuban/UI/mainwindow.py: Add "..." to menu items that will open
+	new dialogs.
+
+	* Thuban/UI/projdialog.py (ProjFrame.__init__): Rearrange the
+	order that the controls are created so that tabbing works correctly.
+	(ProjFrame.OnApply): Renamed from _OnTry() to use wxDialog behaviour.
+	(ProjFrame.OnOK): Renamed from _OnOK() to use wxDialog behaviour.
+	(ProjFrame.OnCancel): Renamed from _OnClose() to use wxDialog behaviour.
+	(ProjPanel.__init__): Add "Airy" to the list of ellipsoids so we
+	can provide the "UK National Grid" as a default projection.
+	(UTMPanel.__init__): Rearrange the order that the controls are 
+	created so that tabbing works correctly.
+
+2003-05-05  Bernhard Herzog  <bh at intevation.de>
+
+	* extensions/thuban/wxproj.cpp: Fix some of the comments.
+	(project_point): If a map projection but no layer projection is
+	given, convert degrees to radians before applying the map
+	projection.
+
+	* Thuban/UI/tableview.py (TableGrid.disallow_messages)
+	(TableGrid.allow_messages): New methods to make it possible to
+	inhibit message sending.
+	(TableGrid.issue): Only send the message if not inhibited.
+	(LayerTableGrid.select_shape): Use the new methods to make sure
+	that no ROW_SELECTED message is sent while we're updating the
+	selected rows to match the selected shapes.
+
+2003-05-02  Jan-Oliver Wagner <jan at intevation.de>
+
+	Implementation of MemoryTable.
+
+	* Thuban/Model/table.py (MemoryTable): New. Quite simple table
+	implementation that operates on a list of tuples. All of the data
+	are kept in the memory.
+
+	* test/test_table.py (MemoryTableTest): New.
+
+	* test/test_transientdb.py (SimpleTable): Removed.
+	(TestTransientTable.test_transient_joined_table,
+	(TestTransientTable.test_transient_table_read_twice): Replaced
+	SimpleTable by MemoryTable.
+
+2003-04-30  Jonathan Coles   <jonathan at intevation.de>
+
+	* Data/iceland_sample.thuban: Now contains correct projections
+	for each of the layers.
+
+	* Resources/Projections/defaults.proj: Geographic projection
+	contains unit conversion parameter.
+
+2003-04-30  Jonathan Coles   <jonathan at intevation.de>
+
+	The most important part of this putback is the projection changes.
+	It should now be possible to specify the projection that a layer
+	is in and then specify a different projection for the map. The
+	projection dialog has an extra parameter for a geographic projection
+	which lets the user select if the input is in degrees or radians.
+
+	* Thuban/Model/layer.py (Layer.ShapesInRegion): Fix docstring
+	to say that the parameter is a tuple of unprojected 
+	points (which is what the callers to this method were assuming).
+	Also, since the points are unprojected we need to projected them.
+
+	* Thuban/UI/legend.py (LegendTree.MoveCurrentItemUp, 
+	LegendTree.MoveCurrentItemDown): If the layer or any of the layer's
+	groups are selected, move the layer up/down. Fixes RTbug #1833.
+
+	* Thuban/UI/mainwindow.py: Move menu item map_rename up.
+
+	* Thuban/UI/projdialog.py (ProjFrame._OnSave): Add missing 
+	parameter in call to SetClientData.
+	(GeoPanel): Add support for selecting the units that the
+	source data is in (Radians or Degrees).
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Optimize
+	the rendering loop by reducing the number of if's, removing the
+	unnecessary try/except block, and checking if the old group
+	is the same as the new one (which happens a lot if there is 
+	no classification, or lots of shapes are in the same group).
+
+	* Thuban/UI/view.py (MapCanvas.OnPaint): Add a try/except block
+	around the redraw routine to try to catch problems that the user
+	may create by selecting invalid projections for the data set and
+	map. Clears the display if there are any problems and prints the
+	error.
+	(MapCanvas.do_redraw): Use DC.Clear() instead of drawing a filled
+	rectangle.
+
+	* extensions/thuban/wxproj.cpp (project_point): First invert the
+	supplied point (which should be in projected coordinates) using
+	the layer's projection and then project the point using the
+	map's projection.
+	(project_points): Use project_point() to project each point.
+
+2003-04-30  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.SetShapeStore): Fixed a bug:
+	don't set the Classification to None if the classfication field
+	is None (ie only a DEFAULT).
+
+2003-04-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py: Fix some typos.
+
+	* Thuban/UI/mainwindow.py (MainWindow.identify_view_on_demand): Do
+	not pop up the dialog if the selection becomes empty (this could
+	happen if e.g. a new selection is opened while the identify tool
+	is active and dialog had been closed)
+
+2003-04-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/transientdb.py (TransientTableBase.__init__): New
+	instance variable read_record_last_result
+	(TransientTableBase.read_record): Make sure reading the same
+	record twice works. The implementation uses the new instance
+	variable read_record_last_result
+
+	* test/test_transientdb.py
+	(TestTransientTable.test_transient_table_read_twice): New test
+	case for the above bug-fix.
+
+2003-04-29  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/common.py: Removed. No longer needed Str2Num. RTbug #1832.
+
+	* Thuban/UI/classgen.py: Remove all uses of Str2Num.
+
+	* Thuban/UI/classifier.py: Remove all uses of Str2Num.
+	(ClassTable.SetValueAsCustom): Rename keyword argument in 
+	ClassGroup* constructors to match argument name.
+
+2003-04-29  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/session.py (Session.Destroy): Explicitly close the
+	transient DB if it exists to make sure it doesn't leave a journal
+	file in the temp directory.
+
+	* Thuban/Model/transientdb.py (TransientDatabase.close): Set
+	self.conn to None after closing the connection to make sure it's
+	not closed twice
+
+2003-04-29  Jonathan Coles   <jonathan at intevation.de>
+
+	Add a visible parameter in the layer XML tag. The default value is
+	"true". If anything other than "false" is specified we also assume
+	"true". Addresses RTbug #1025.
+
+	* Doc/thuban.dtd: Add visible parameter to a layer.
+
+	* Thuban/Model/layer.py (BaseLayer.__init__): Change default value
+	of visible from 1 to True.
+	(Layer.__init__): Change default value of visible from 1 to True.
+
+	* Thuban/Model/load.py (SessionLoader.start_layer): Read visible
+	parameter.
+
+	* Thuban/Model/save.py (SessionSaver.write_layer): Save visible
+	parameter.
+
+	* test/test_load.py: Add new test data contents_test_visible.
+	(LoadSessionTest.setUp): save test data.
+	(LoadSessionTest.testLayerVisibility): Test if the visible flag
+	is loaded correctly.
+
+	* test/test_save.py (SaveSessionTest.testSingleLayer): Add test
+	for saving an invisible layer.
+
+2003-04-29  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.SetMap): Look up the
+	legend dialog box and tell it to change its map to the one
+	supplied to SetMap(). Fixes RTbug #1770.
+
+2003-04-29  Bernhard Herzog  <bh at intevation.de>
+
+	Next step of table implementation. Introduce a transient database
+	using SQLite that some of the data is copied to on demand. This
+	allows us to do joins and other operations that require an index
+	for good performance with reasonable efficiency. Thuban now needs
+	SQLite 2.8.0 and pysqlite 0.4.1. Older versions may work but I
+	haven't tested that.
+	
+	* Thuban/Model/transientdb.py: New. Transient database
+	implementation.
+
+	* test/test_transientdb.py: New. Tests for the transient DB
+	classes.
+
+	* Thuban/Model/session.py (AutoRemoveFile, AutoRemoveDir): New
+	classes to help automatically remove temporary files and
+	directories.
+	(Session.__init__): New instance variables temp_dir for the
+	temporary directory and transient_db for the SQLite database
+	(Session.temp_directory): New. Create a temporary directory if not
+	yet done and return its name. Use AutoRemoveDir to have it
+	automatically deleted
+	(Session.TransientDB): Instantiate the transient database if not
+	done yet and return it.
+
+	* Thuban/Model/data.py (ShapefileStore.__init__): Use an
+	AutoTransientTable so that data is copied to the transient DB on
+	demand.
+	(SimpleStore): New class that simply combines a table and a
+	shapefile
+
+	* Thuban/Model/table.py (Table, DBFTable): Rename Table into
+	DBFTable and update its doc-string to reflect the fact that this
+	is only the table interface to a DBF file. Table is now an alias
+	for DBFTable for temporary backwards compatibility.
+
+	* Thuban/UI/application.py (ThubanApplication.OnExit): Make sure
+	the last reference to the session goes away so that the temporary
+	files are removed properly.
+
+	* test/test_load.py (LoadSessionTest.tearDown): Remove the
+	reference to the session to make sure the temporary files are
+	removed.
+
+2003-04-29  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/load.py (XMLReader.__init__, XMLReader.read): Turn
+	the __parser instance variable into a normal local variable in
+	read. It's only used there and read will never be called more than
+	once. Plus it introduces a reference cycle that keeps can keep the
+	session object alive for a long time.
+
+2003-04-29  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/proj.py (Projection): Removed Set*() methods to make 
+	Projection an immutable item. Fixes RTbug #1825. 
+	(Projection.__init__): Initialize instance variables here.
+	(ProjFile.Replace): New. Replace the given projection object with
+	the new projection object. This solves the problem of needing the 
+	mutator Projection.SetProjection() in the ProjFrame class and
+	allows a projection to change parameters without changing its 
+	location in the file.
+
+	* Thuban/UI/mainwindow.py (MainWindow.SaveSessionAs): Dialog should
+	be of type wxSAVE and should verify overwriting a file.
+
+	* Thuban/UI/projdialog.py (ProjFrame._OnSave): Use the new 
+	ProjFile.Replace() method instead of the mutator 
+	Projection.SetProjection(). Also requires that we reassign the
+	client data to the new projection.
+
+	* test/test_proj.py (TestProjection.test): Test GetName() and
+	GetAllParameters()
+	(TestProjFile.test): Remove tests for Set*() methods. Add tests
+	for Replace().
+
+2003-04-25  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/save.py (SessionSaver.write_projection): Make sure
+	to save the name of the projection.
+
+	* test/test_save.py (SaveSessionTest.testLayerProjection): New
+	test to verify layer projections are saved correctly.
+
+2003-04-25  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/proj.py (Projection.SetName): Set the name
+	to "Unknown" if name is None.
+	(Projection.SetAllParameters): New. Set the projection's
+	parameter list to the one supplied.
+	(Projection.SetProjection): New. Set the projection's 
+	properties to those of the supplied Projection.
+
+	* Thuban/UI/mainwindow.py (MainWindow.MapProjection): Set
+	the dialog title to include the map's title.
+	(MainWindow.LayerProjection): Set the dialog title to include
+	the layer's title.
+
+	* Thuban/UI/projdialog.py (ProjFrame.__ShowError): Consolidate
+	error dialogs into a single method call.
+	(ProjFrame.__VerifyButtons): Add more states to check.
+	(ProjFrame.__GetProjection): Return the current state of an
+	edited projection or None.
+	(ProjFrame.__FillAvailList): Remove checks for states that
+	shouldn't exist.
+	(ProjFrame._OnNew): Clear all selected items and supply
+	a projection panel if necessary.
+
+	* test/test_proj.py (TestProjFile.test): Add tests for
+	ProjFile.SetAllParameters, ProjFile.SetProjection,
+	ProjFile.SetName.
+
+2003-04-25  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/projdialog.py (ProjFrame.__FillAvailList): Now 
+	takes an optional argument to select the current projection.
+	This does not guarantee that the item is visible due to
+	limited wxWindows functionality. Fixes RTBug #1821.
+
+2003-04-25  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/load.py (SessionLoader.start_projection): Remember
+	the projection name and use it when constructing the Projection
+	object.
+
+	* Thuban/Model/proj.py (Projection.__init__): Change the default
+	value for 'name' to None and then test if name is equal to None
+	in the body of the constructor. This way the caller doesn't have to
+	know what the default value should be. Namely, useful in load.py 
+	where we have to pick a default value if the 'name' parameter
+	doesn't exist in the XML file.
+
+	* test/test_load.py (LoadSessionTest.testLayerProjection): New.
+	Tests a file where a layer has a projection.
+
+2003-04-25  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.TreeInfo): Add an item to the
+	tree for projection information.
+
+	* Thuban/Model/load.py (XMLReader.GetFilename): Renamed from 
+	XMLReader.GetFileName.
+	(SessionLoader): Added support for loading projection tags that
+	appear inside a layer.
+
+	* Thuban/Model/proj.py (ProjFile): Document the class. Move 
+	back to using a list because the order of the projections in 
+	the file is important to maintain. Fixes RTbug #1817.
+
+	* Thuban/Model/resource.py: Rename calls to ProjFile.GetFileName
+	to ProjFile.GetFilename.
+
+	* Thuban/Model/save.py (SessionSaver.write_layer): Save projection
+	information.
+
+	* Thuban/UI/projdialog.py (ProjFrame._OnAddToList): Renamed from
+	ProjFrame._OnSaveAs. Removed old dead code from previous
+	implementation.
+	(ProjFrame._OnExport): Add support for exporting more than one
+	projection to a single file.
+	(ProjFrame.__FillAvailList): use string formatting (% operator) 
+	to build strings that are (partly) translated. Fixes RTbug #1818.
+
+	* test/test_proj.py (TestProjFile.test): New. Tests the base ProjFile
+	class.
+
+2003-04-24  Bernhard Herzog  <bh at intevation.de>
+
+	* po/es.po: Updated Spanish translation by Daniel Calvelo Aros
+
+	* po/fr.po: New. French translation by Daniel Calvelo Aros
+
+	* Thuban/UI/projdialog.py (ProjFrame._OnSaveAs): Don't translate
+	empty strings.
+
+2003-04-24  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.GetProjection): New. Needed to
+	implement the interface that the ProjFrame dialog expects.
+
+	* Thuban/Model/proj.py (Projection.SetName): New. Allows the
+	name of the projection to be changed.
+	(ProjFile): Use a dictionary instead of a list so that removing
+	projections is easier and we are sure about uniqueness.
+	(ProjFile.Remove): Remove the given projection object.
+
+	* Thuban/Model/resource.py (GetSystemProjFiles, GetUserProjFiles): 
+	Return a list with only one projection file instead of searching for 
+	any projection file. This simplifies many things if the user can
+	only have one system file and one user file.
+
+	* Thuban/UI/classgen.py: Change all references to 
+	genCombo to genChoice.
+
+	* Thuban/UI/mainwindow.py: Add a Projection option under the
+	layer menu.
+	(MainWindow.LayerProjection): New. Open up a projection window
+	for a layer.
+
+	* Thuban/UI/projdialog.py: Large changes to how the dialog is
+	laid out. Use three panels instead of one. One for the list of
+	projections, one for the edit controls, and one for the buttons.
+	Fixed resizing problems so that the dialog resizes correctly
+	when the projection panel changes. Added import/export, save, and
+	new buttons/functionality.
+
+2003-04-24  Bernhard Herzog  <bh at intevation.de>
+
+	First step towards table management. Introduce a simple data
+	abstraction so that we replace the data a layer uses more easily
+	in the next step.
+
+	* Thuban/Model/data.py: New file with a simple data abstraction
+	that bundles shapefile and dbffile into one object.
+
+	* Thuban/Model/session.py (Session.OpenShapefile): New method to
+	open shapefiles and return a shape store object
+
+	* Thuban/Model/layer.py (Layer.__init__): Pass the data as a store
+	object instead of a shapefile filename. This introduces a new
+	instance variable store holding the datastore. For intermediate
+	backwards compatibility keep the old instance variables.
+	(open_shapefile): Removed. No longer needed with the shape store.
+	(Layer.SetShapeStore, Layer.ShapeStore): New methods to set and
+	get the shape store used by a layer.
+	(Layer.Destroy): No need to explicitly destroy the shapefile or
+	table anymore.
+
+	* Thuban/UI/mainwindow.py (MainWindow.AddLayer)
+	(MainWindow.AddLayer): Use the session's OpenShapefile method to
+	open shapefiles
+
+	* Thuban/Model/load.py (ProcessSession.start_layer): Use the
+	session's OpenShapefile method to open shapefiles
+
+	* test/test_classification.py
+	(TestClassification.test_classification): Use the session's
+	OpenShapefile method to open shapefiles and build the filename in
+	a more platform independed way
+
+	* test/test_layer.py (TestLayer.setUp, TestLayer.tearDown):
+	Implement to have a session to use in the tests
+	(TestLayer.test_arc_layer, TestLayer.test_polygon_layer)
+	(TestLayer.test_point_layer, TestLayer.test_empty_layer): Use the
+	session's OpenShapefile method to open shapefiles
+	(TestLayerLegend.setUp): Instantiate a session so that we can use
+	it to open shapefiles.
+	(TestLayerLegend.tearDown): Make sure that all references to
+	layers and session are removed otherwise we may get a resource
+	leak
+
+	* test/test_map.py (TestMapAddLayer.test_add_layer)
+	(TestMapWithContents.setUp): Instantiate a session so that we can
+	use it to open shapefiles.
+	(TestMapWithContents.tearDown): Make sure that all references to
+	layers, maps and sessions are removed otherwise we may get a
+	resource leak
+	("__main__"): use support.run_tests() so that more info about
+	uncollected garbage is printed
+
+	* test/test_save.py (SaveSessionTest.testSingleLayer): Use the
+	session's OpenShapefile method to open shapefiles
+	("__main__"): use support.run_tests() so that more info about
+	uncollected garbage is printed
+
+	* test/test_selection.py (TestSelection.tearDown): Make sure that
+	all references to the session and the selection are removed
+	otherwise we may get a resource leak
+	(TestSelection.get_layer): Instantiate a session so that we can
+	use it to open shapefiles.
+	("__main__"): use support.run_tests() so that more info about
+	uncollected garbage is printed
+
+	* test/test_session.py (TestSessionBase.tearDown)
+	(TestSessionWithContent.tearDown): Make sure that all references
+	to the session and layers are removed otherwise we may get a
+	resource leak
+	(TestSessionWithContent.setUp): Use the session's OpenShapefile
+	method to open shapefiles
+
+2003-04-24  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/load.py (XMLReader.read): Should have been checking
+	if the file_or_filename object had the 'read' attribute.
+
+2003-04-23  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/resource.py: Fixes RTbug #1813.
+	(ReadProjFile): Add documentation about which exceptions are raised. 
+	Always pass the exceptions up to the caller.
+	(GetProjFiles): If the directory can't be read return an empty list.
+	If any of the proj files can't be read skip that file and go
+	on to the next one.
+
+	* test/test_proj.py: Added test cases to handle nonexistent files,
+	unreadable files, and files that don't parse correctly.
+
+2003-04-23  Jonathan Coles   <jonathan at intevation.de>
+
+	Projection dialog. Allows the user to select from a list
+	of projection templates and optionally edit them and save new ones.
+
+	* Thuban/UI/projdialog.py (ProjFrame): New. Main dialog.
+	(ProjPanel): Base class for projection specific panels.
+	(TMPanel): Projection panel for Transverse Mercartor.
+	(UTMPanel): Projection panel for Universal Transverse Mercartor.
+	(LCCPanel): Projection panel for Lambert Conic Conformal.
+	(GeoPanel): Projetion panel for Geographic Projection.
+
+2003-04-23  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/load.py (XMLReader): Renamed from XMLProcessor to
+	promote symmetry. There now exists XMLReader and XMLWriter.
+	(XMLReader.read): New. Call to read the given file descriptor or
+	filename.
+	(XMLReader.close): New. Make sure the file is closed.
+	(XMLReader.GetFileName): New. Return just the file name that is being
+	read from.
+	(XMLReader.GetDirectory): New. Return just the directory of the file
+	that is being read.
+	(XMLReader.AddDispatchers): New. Take a dictionary which contains
+	the names of functions to call as the XML tree is parsed.
+	(XMLReader.startElementNS): Updated to use new dispatcher dictionary.
+	(XMLReader.endElementNS): Updated to use new dispatcher dictionary.
+	(SessionLoader): Removed class variables start_dispatcher and
+	end_dispatcher since this functionality is now part of a class
+	instance. Fixes RTbug #1808.
+	(SessionLoader.__init__): Add dispatcher functions.
+	(load_xmlfile): Code was moved into the XMLReader.read().
+	(load_session): Use modified SessionLoader.
+
+	* Thuban/Model/map.py (Map.GetProjection): New. Returns the 
+	map's projection.
+
+	* Thuban/Model/proj.py (Projection.GetParameters): Renamed to 
+	GetAllParameters. 
+	(Projection.GetParameter): Returns the value for the given parameter.
+
+	* Thuban/Model/resource.py: Use XMLReader and XMLWriter.
+	(GetProjFiles): Renamed from GetProjections. Now returns a list
+	of ProjFile objects.
+	(GetSystemProjFiles): Renamed from GetSuppliedProjections. Returns
+	a list of ProjFile objects whose files are not user defined.
+	(GetUserProjFiles): Renamed from GetUserProjections. Returns a
+	list of ProjFile objects whose files are user defined.
+	(ProjFileReader): Extend new XMLReader.
+
+	* Thuban/Model/save.py (XMLWriter): Renamed from XMLSaver to
+	promote symmetry.
+
+	* Thuban/UI/classgen.py (ClassGenDialog.__init__): Use a wxChoice
+        control instead of a wxComboBox. wxChoice controls do not generate
+	events as the uses highlights possible choices which fixes problems
+	with resizing the dialog when the use selects an option.
+
+	* Thuban/UI/classifier.py (Classifier.__init__): Use a wxChoice
+	control instead of a wxComboBox.
+
+	* Thuban/UI/mainwindow.py (MainWindow.Projection): Use new projection
+	dialog.
+
+	* test/test_proj.py (TestProjection.test): New tests for GetParameter
+	method.
+
+2003-04-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py: Remove some unused imports and global
+	constants
+
+	* Thuban/UI/identifyview.py (IdentifyListCtrl.selected_shape)
+	(IdentifyGridCtrl.selected_shape): Use table, not shapetable.
+
+2003-04-17  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py: Don't import LAYER_LEGEND_CHANGED.
+	(Layer): Update doc-string since LAYER_LEGEND_CHANGED is not used
+	anymore.
+	(Layer.BoundingBox, Layer.GetFieldType, Layer.NumShapes)
+	(Layer.ShapeType, Layer.Shape): No need to call
+	self.open_shapefile since it's always called in __init__
+
+	* Thuban/UI/application.py (ThubanApplication.MainLoop): Removed.
+	In wxPython 2.4 there's no need to extend MainLoop anymore since
+	wxPython itself makes sure OnExit is called.
+
+2003-04-16  Jonathan Coles   <jonathan at intevation.de>
+
+	Initial putback of projection management code. Includes new
+	classes to read and write projection files. The current load
+	and save classes were abstracted a bit so they could be reused.
+	The Projection class was extended to provide new methods and
+	have a name.
+
+	* Thuban/Model/load.py (XMLProcessor): New. Contains all the
+	general XML reading methods that were part of ProcessSession.
+
+	* Thuban/Model/proj.py (Projection.__init__): Accepts an optional
+	name.
+	(ProjFile): New. Represents a file that contains projection
+	information.
+
+	* Thuban/Model/resource.py: New. Contains general utilities
+	for read and writing projection files.
+
+	* Thuban/Model/save.py (XMLSaver): New. Contains all the 
+	general XML writing methods that were part of SessionSaver.
+	(SessionSaver): Renamed from Saver.
+
+	* test/test_proj.py: New test cases for the projection
+	file read and write functions.
+
+2003-04-16  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py: Use repr() around values 
+	in the ClassGroup*.__repr__() methods so it is clearer when
+	a value is a string and when it is a number.
+
+	* test/test_load.py: Rework the classification test to test
+	that we can load old files. 
+	(testLabels): Test a file where the groups have labels.
+
+2003-04-16  Bernhard Herzog  <bh at intevation.de>
+
+	Safer implementation of the performance enhancements of the
+	low-level renderer:
+	
+	* extensions/thuban/wxproj.cpp (extract_projection)
+	(extract_pointer): Rename extract_projection to extract_pointer
+	and redefine its purpose to return the pointer stored in a CObject
+	returned by the object's cobject method. Update all callers.
+	(s_draw_info, free_draw_info, draw_polygon_init): Implement the
+	handling of these low-level parameters so that each s_draw_info
+	instance is handled as a CObject at python level that also
+	contains real references to the actual python objects which
+	contain the values in the struct. Add free_draw_info as the
+	destructor.
+	(draw_polygon_shape): Add the py_draw_info parameter which must a
+	cobject containing an s_draw_info pointer.
+
+	* Thuban/UI/renderer.py (MapRenderer.polygon_render_param): New
+	method to instantiat the low-level render parameter
+	(MapRenderer.draw_shape_layer): Use the new method. Remove some
+	commented out code.
+	(MapRenderer.draw_polygon_shape): Make the first parameter not the
+	layer but the low-level render parameter
+	(ScreenRenderer.draw_shape_layer): Use the low-level render
+	parameter.
+
+2003-04-15  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py: Implemented __repr__ for
+	the ClassGroup* classes to make debugging a bit easier.
+	(ClassGroup.SetLabel): Check that the string is an instance
+	of StringTypes not StringType. Accounts for Unicode strings.
+
+	* Thuban/Model/color.py: Implemented __repr__ to make 
+	debugging a bit easier.
+
+	* Thuban/Model/save.py (Saver.write_classification): Need to
+	save the group label.
+
+	* test/test_load.py (testClassification): New. Loads the
+	iceland_sample_test.thuban file and checks if it was loaded
+	correctly.
+
+2003-04-15  Jonathan Coles   <jonathan at intevation.de>
+
+	* extensions/thuban/wxproj.cpp (draw_polygon_init): New. Used
+	to improve rendering performance by initializing the variables
+	that are not change each time draw_polygon_shape() is called.
+	The values are stored in a global struct draw_info.
+	(draw_polygon_shape): Removed initialization code that is
+	now in draw_polygon_init().
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Make
+	drawing initialization call to draw_polygon_init()
+	(MapRenderer.draw_polygon_shape): Use new signature of
+	draw_polygon_shape.
+
+	* Thuban/UI/classgen.py (GenUniformPanel): Fix spin control
+	weirdness by setting the range to (1, maxint).
+
+	* Thuban/Model/classification.py (ClassGroupProperties): Make
+	instance variables private and optimize comparison operator
+	by first checking if the color references are the same.
+	(ClassGroupSingleton): Make instance variables private.
+	(ClassGroupRange): Make instance variables private.
+
+	* HOWTO-Release: Filled in missing steps for releasing packages.
+
+2003-04-15  Bernhard Herzog  <bh at intevation.de>
+
+	First stab at internationalized messages:
+
+	* Thuban/__init__.py (_): Implement the translation function for
+	real using the python gettext module.
+
+	* Thuban/UI/classifier.py (ClassTable.GetRowLabelValue): Don't
+	translate empty strings.
+
+	* Thuban/UI/application.py (ThubanApplication.read_startup_files):
+	Add a missing space to a warning message
+
+	* po/README: New. Notes about the management of the translation
+	files.
+
+	* po/Makefile: New. Makefile to help manage the translation files.
+
+	* po/es.po: New. Spanish translation by Daniel Calvelo Aros
+
+	* MANIFEST.in: Include the *.mo files in Resources/Locale and the
+	translations and support files in po/
+
+	* setup.py (data_files): Add the *.mo files to the data_files too
+
+	* README: Add note about the translations when building from CVS
+
+2003-04-14  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/dock.py: Fixes some window resizing problems most
+	noticable under windows. Always assume the button bitmaps will 
+	be there. Code clean up. 
+	(DockabelWindow.Dock, DockableWindow.UnDock): Force all the
+	images for the dock/undock button to the same images.
+	Work around for RTbug #1801. 
+
+	* Thuban/UI/legend.py (LegendPanel.__init__): The toolbar should
+	be allowed to grow within the sizer. Fixes a bug under Windows
+	where the toolbar wasn't being drawn.
+
+2003-04-14  Frank Koormann   <frank.koormann at intevation.de>
+
+	* Resources/Bitmaps/dock_12.xpm, Resources/Bitmaps/undock_12.xpm:
+	Updated design to try to make the button functionality more
+	transparent.
+
+2003-04-14  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/legend.py (LegendPanel.__init__): Call Create() to
+	finalize the intialization of the panel.
+
+	* Thuban/UI/dock.py (DockPanel.Create): New. Finalizes the 
+	creation of the panel. Should be the last thing called in the
+	initializer of a subclass.
+
+	* Thuban/UI/classgen.py (ClassGenDialog.__init__): Actively
+	set the current selections in the combo boxes. This is needed
+	under Windows.
+
+	* Thuban/UI/classifier.py (Classifier.__init__): Add a top
+	level panel to the dialog so that the background colors are
+	consistent under Windows.
+
+2003-04-11  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classgen.py: Change color ramps to start at white 
+	not black.
+
+	* Thuban/UI/legend.py: Enable/disable the legend buttons when
+	the legend changes. Fixes RTbug #1793.
+
+	* test/test_classification.py: Added test for copying of
+	classifications.
+
+2003-04-11  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/resource.py: New. Centralize the loading of resources 
+	such as bitmaps.
+
+	* Thuban/UI/classgen.py (GenUniquePanel.__init__): Reordered buttons,
+	added images to the move buttons, added 'reverse' button.
+	(CustomRampPanel.__init__): Added images to the move buttons.
+	(GreyRamp): New. Generates a ramp from white to black.
+	(HotToColdRamp): New. Generates a ramp from cold to hot colors.
+
+	* Thuban/UI/classifier.py: Refactored ID's from ID_CLASSIFY_* to
+	ID_PROPERTY_*.
+	(Classifier.__init__): Minor changes to the layout.
+	(Classifier._OnTitleChanged): Listen for when the user edits the
+	title and update the dialog's title and the layer's title.
+
+	* Thuban/UI/dock.py: Use new bitmaps for the control buttons.
+
+	* Thuban/UI/legend.py: Use new bitmaps for the control buttons.
+	(LegendTree._OnMsgLayerTitleChanged): Change the displayed title
+	if the layer's title changes.
+
+	* Thuban/UI/mainwindow.py: Added new menu item and associated code
+	to open a dialog to rename the map. 
+	(MainWindow): Use new resource class to import bitmaps.
+
+2003-04-11  Jonathan Coles   <jonathan at intevation.de>
+
+	* Resources/Bitmaps/close_12.xpm, Resources/Bitmaps/dock_12.xpm,
+	Resources/Bitmaps/group_use.xpm, Resources/Bitmaps/group_use_all.xpm,
+	Resources/Bitmaps/group_use_none.xpm, 
+	Resources/Bitmaps/group_use_not.xpm,
+	Resources/Bitmaps/hide_layer.xpm, 
+	Resources/Bitmaps/layer_properties.xpm,
+	Resources/Bitmaps/lower_layer.xpm, Resources/Bitmaps/raise_layer.xpm,
+	Resources/Bitmaps/show_layer.xpm, Resources/Bitmaps/undock_12.xpm:
+	New.
+
+2003-04-10  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py: (ClassGroupRange.__init__): 
+	Should pass group to ClassGroup constructor.
+
+2003-04-10  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py: (ClassGroup): Move all the common
+	methods of the derived classes ([Set|Get]Properties(), __eq__, __ne__)
+	here. Implement SetVisible(), IsVisible().
+	(ClassGroup.__init__): Add group parameter which acts as a copy
+	constructor.
+
+	* Thuban/UI/classifier.py (ClassTable): Add a new column for the
+	"Visible" check boxes.
+	(Classifier): Rename the buttons and refactor the code to match
+	the new labels.
+
+	* Thuban/UI/legend.py: Classify button is now called "Properties".
+	Refactored the code to change variable names.
+	(LegendTree.__FillTreeLayer): Only list a group if it is visible.
+
+	* Thuban/UI/mainwindow.py: MainWindow.OpenClassifier renamed to
+	MainWindow.OpenLayerProperties. MainWindow.LayerEditProperties
+	renamed to MainWindow.LayerEditProperties.
+	(MainWindow.ToggleLegend): Don't include map name in legend title.
+	(MainWindow.SetMap): Added the map name to the window title.
+	(MainWindow.LayerFillColor, MainWindow.LayerTransparentFill,
+	MainWindow.LayerOutlineColor, MainWindow.LayerNoOutline): Removed.
+	Functionality is found in the layer properties dialog.
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Only
+	draw visible groups.
+
+2003-04-09  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classgen.py: Modifications to allow simple
+	addition and selection of new color schemes.
+	(MonochromaticRamp): New. Generates a ramp between two colors.
+	(RedRamp): New. Generates a ramp of all red.
+	(GreenRamp): New. Generates a ramp of all green.
+	(BlueRamp): New. Generates a ramp of all blue.
+
+2003-04-09  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py (Classification.__deepcopy__):
+	Need to copy over field and fieldType attributes.
+
+	* Thuban/Model/table.py (Table.field_range): New. Retrive the
+	maximum and minimum values over the entire table for a given
+	field.
+	(Table.GetUniqueValues): New. Retrieve all the unique values
+	in the table for a given field.
+
+	* Thuban/UI/classgen.py: Renamed GenRangePanel to GenUniformPanel.
+	(GenUniquePanel): New. Controls to allow the user to select
+	which unique field values they would like in the classification.
+	(CustomRampPanel): Code that was in ClassGenDialog that allows
+	the user to select the properties for a custom ramp.
+	(ClassGenerator.GenUniformDistribution): Was called GenerateRanges.
+
+	* Thuban/UI/classifier.py: Removed a lot of debugging code.
+	(Classifier._SetClassification): Callback method so that the
+	class generator can set the classification in the grid.
+	(ClassGroupPropertiesCtrl): New. Encapsulates the drawing and
+	editing of a group properties class into a wxWindows control.
+
+	* Thuban/UI/dock.py: It was decided that if the user closes
+	a dockable window the window should simply hide itself. That
+	way if the user wants to show the dock again it appears in the
+	same place as it was when it was closed.
+	(DockableWindow.Destroy): Call renamed method OnDockDestroy().
+	(DockableWindow._OnButtonClose): Hide the window instead of 
+	destroying it.
+	(DockableWindow._OnClose): Hide the window instead of 
+	destroying it.
+
+	* Thuban/UI/legend.py (LegendTree): Use a private method to 
+	consistently set the font and style of the text. Fixes RTbug #1786.
+
+	* Thuban/UI/mainwindow.py: Import just the Classifier class.
+
+2003-04-07  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (main_menu): Move the toggle_legend item
+	to the map module
+
+2003-04-07  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.ShowSessionTree): Removed in
+	favor of ToggleSessionTree
+	(MainWindow.ToggleSessionTree): New method to toggle visibility of
+	the session tree.
+	(MainWindow.SessionTreeShown): New method to return whether the
+	session tree is currently shown.
+	(MainWindow.ToggleLegend): New method to toggle visibility of the
+	legend
+	(MainWindow.ShowLegend): Implement in terms of ToggleLegend and
+	LegendShown
+	(MainWindow.LegendShown): New method to return whether the legend
+	is currently shown.
+	(_method_command): Add checked parameter so we can define check
+	menu items
+	(_has_tree_window_shown, _has_legend_shown): Use the appropriate
+	mainwindow methods.
+	(show_session_tree, show_legend commands): Removed.
+	(toggle_session_tree, toggle_legend commands): New commands to
+	toggle the visibility of the dialogs
+
+2003-04-07  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classgen.py: Fix Windows problem.
+
+	* Thuban/UI/dock.py: Fix Windows problem.
+
+	* Thuban/UI/mainwindow.py: Use False instead of false.
+	(MainWindow.ShowLegend): Remove unnecessary switch parameter.
+
+2003-04-07  Jonathan Coles   <jonathan at intevation.de>
+
+	Since we now say that the order of the groups in a classification
+	matters, it makes sense to be able to manipulate that order. Most
+	of the changes to Thuban/Model/classification.py are to that end.
+
+	* Thuban/Model/classification.py (Classification.AppendGroup,
+	Classification.InsertGroup, Classification.ReplaceGroup,
+	Classification.RemoveGroup, Classification.GetGroup): Do as the
+	names imply.
+	(Classification.FindGroup): This was called GetGroup, but GetGroup
+	takes an index, while FindGroup takes a value.
+	(Classification.__deepcopy__): Copy all the groups, BUT NOT THE LAYER
+	REFERENCE. Currently there is a cyclic reference between the layer
+	and its classification. If the classification doesn't need to know
+	its owning layer we can change this, since it may make sense to be
+	able to use the same classification with different layers.
+
+	* Thuban/Model/load.py: Use Classification.AppendGroup(), not AddGroup()
+
+	* Thuban/UI/classgen.py: Use Classification.AppendGroup(), 
+	not AddGroup()
+
+	* Thuban/UI/classifier.py: Now that we can depend on the order in 
+	a Classification and have methods to manipulate that order we don't
+	need to use our own data structures in the grid. We can simply make
+	the grid/table access the information they need from a copy of 
+	the classification object.
+	(Classifier._OnCloseBtn): Event handler for when the user clicks
+	'Close'. This is needed so if the user applies changes and then
+	continues to change the table the user has the option of discarding
+	the most recent changes and keeping what they applied.
+
+	* Thuban/UI/mainwindow.py: Put "Show Legend" and "Show Session Tree"
+	into the same group.
+
+	* extensions/thuban/wxproj.cpp (check_version): If Thuban is compiled
+	with a really old version of proj, PJ_VERSION won't even be defined.
+	If it isn't defined then just compile so that the function always
+	returns Py_False.
+
+	* test/test_classification.py: Fix tests to use the renamed methods.
+	Still need to write tests for the new methods.
+
+2003-04-04  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classifier.py (Classifier.__SelectField): Move the
+	call to SetSelection out of the method and before the call
+	to __SelectField in __init__. This prevents a recursion of events
+	when _OnFieldSelect is triggered by the user.
+
+2003-04-04  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py: Rename Color.None to 
+	Color.Transparent.
+	(ClassGroupProperties.SetLineColori, ClassGroupProperties.SetFill): 
+	Don't bother copying the color, since Colors are immutable.
+
+	* Thuban/Model/color.py, Thuban/Model/layer.py, Thuban/Model/load.py,
+	Thuban/UI/classifier.py, Thuban/UI/mainwindow.py,
+	Thuban/UI/renderer.py, Thuban/UI/view.py:
+	Rename Color.None to Color.Transparent.
+    
+	* test/test_classification.py, test/test_load.py: Rename Color.None 
+	to Color.Transparent.
+
+2003-04-04  Jonathan Coles   <jonathan at intevation.de>
+ 
+	* Thuban/Model/classification.py: Fix assert calls.
+	(ClassGroupProperties.SetLineColor, ClassGroupProperties.SetFill):
+	Copy the color parameter rather than hold onto a reference.
+
+	* Thuban/Model/color.py (Color.__copy__, Color.__deepcopy): Copy
+	the color object.
+	(NoColor.__copy__, NoColor.__deepcopy): Return 'self' so that we
+	are sure there exists only one refernce to Color.None in the system.
+	This allows us to use 'is' rather than the comparision functions.
+	
+	* Thuban/Model/save.py: Fix assert calls.
+	
+	* Thuban/UI/classifier.py: Fix assert calls.
+	(ClassGrid._OnCellDClick): Call up to the classifier to open the 
+	dialog to edit the groups properties.
+	(ClassGrid._OnCellResize): Make sure that the scollbars are drawn
+	correctly if a cell is resized.
+	(ClassTable.SetClassification): New. Changes the classification
+	that is in the table.
+	(ClassTable.__SetRow): Allow groups to be prepended.
+	(Classifier): New code for opening the EditProperties and 
+	GenerateRanges dialogs.
+	(SelectPropertiesDialog.__GetColor): Only set the color in the
+	color dialog if the current color is not None.
+	
+	* Thuban/UI/dock.py: Fix assert calls.
+	
+	* Thuban/UI/legend.py: Fix assert calls.
+	
+	* Thuban/UI/renderer.py: Fix assert calls.
+	
+	* Thuban/UI/classgen.py (ClassGenDialog): Dialog for generating
+	classifications.
+	(GenRangePanel): Panel specific to range generation.
+	(GenSingletonPanel): Panel specific to singleton generation.
+	(ClassGenerator): Class responsible for actually generating
+	the classification from the data gathered in the dialog box.
+	(PropertyRamp): Generates properties whose values range from
+	a starting property to an ending property.
+
+2003-04-03  Bernhard Herzog  <bh at intevation.de>
+
+	* test/support.py (print_garbage_information): New function that
+	prints information about still connected messages and memory
+	leaks.
+	(run_suite): Removed.
+	(run_tests): New function for use as a replacement of
+	unittest.main in the test_* files. This one calls
+	print_garbage_information at the end.
+
+	* test/runtests.py (main): Use support.print_garbage_information
+
+	* test/test_layer.py: Use support.run_tests instead of
+	unittest.main so we get memory leak information
+	(TestLayer.test_arc_layer, TestLayer.test_polygon_layer)
+	(TestLayer.test_point_layer, TestLayer.test_empty_layer)
+	(TestLayerLegend.test_visibility): Call the layer's Destroy method
+	to fix a memory leak.
+
+	* test/test_classification.py: Use support.run_tests instead of
+	unittest.main so we get memory leak information
+	(TestClassification.test_classification): Call the layer's Destroy
+	method to fix a memory leak.
+
+2003-04-02  Bernhard Herzog  <bh at intevation.de>
+
+	* extensions/thuban/wxproj.cpp (check_version, check_version_gtk):
+	Handle the reference counts of the return value and errors in
+	PyArg_ParseTuple correctly.
+
+	* Thuban/UI/application.py (ThubanApplication.OpenSession): Make
+	sure the filename is absolute to avoid problems when saving the
+	session again
+
+	* Thuban/Model/table.py: Remove unnecessary import. Fix a typo.
+
+2003-04-01  Jonathan Coles   <jonathan at intevation.de>
+
+	*  Thuban/UI/renderer.py (MapRenderer.draw_point_shape): Check
+	that there actually are points in the returned list of points
+	before trying to index into the list. The list may be empty if
+	the shape is a Null Shape.
+
+2003-04-01  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_map.py: Don't use from <module> import *
+
+2003-04-01  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/session.py: Use LAYER_CHANGED instead of 
+	LAYER_LEGEND_CHANGED
+
+	* Thuban/UI/dock.py (DockableWindow._OnButtonClose): Call
+	self.Destroy() to close the window after yesterday's changes.
+
+	* test/test_map.py, test/test_session.py: Fix messages that
+	are sent from maps and layers.
+
+2003-03-31  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classifier.py: Commented out some debugging statements.
+	(ClassDataPreviewer.Draw): Draw rectangles for polygon layers per
+	RTbug #1769.
+
+	* Thuban/UI/dock.py (DockableWindow.UnDock): Restore size and 
+	position (although position doesn't work yet under GTK).
+	(DockableWindow.Destroy): New. Called when the window must be
+	closed. Namely needed when the DockFrame closes and must close
+	its children.
+	(DockFrame): Listen for EVT_CLOSE and destroy all children.
+
+	* Thuban/UI/legend.py (LegendPanel.Destroy): New. Cleans up
+	when then window is told to close.
+	(LegendTree._OnMsgLayerChanged): Fixes a seg fault bug. See
+	comment in source for more info.
+
+	* Thuban/UI/main.py: Show the legend by default when Thuban starts.
+
+	* Thuban/UI/mainwindow.py: Renamed OnClose to _OnClose for
+	symmetry with other such methods.
+	(MainWindow.ShowLegend): Show the legend docked by default.
+
+2003-03-28  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classifier.py: Support for highlighting a specific
+	group within the grid when the classification dialog is opened.	
+	Also contains a lot of debugging printouts which will later
+	be removed.
+
+	* Thuban/UI/dock.py: Complete rework on the dock code so that
+	that it is fairly removed from the rest of the Thuban application.
+	It is easy to add new docks which the rest of the program having
+	to be aware of them.
+
+	* Thuban/UI/legend.py: Modifications to support selecting a 
+	specific group in the classification dialog. Changed how layers
+	are drawn when the layer is visible/invisible.
+
+	* Thuban/UI/mainwindow.py: Removed legend specific code and
+	replaced it with calls to the new dock code.
+
+	* Thuban/UI/renderer.py (MapRenderer.__init__): Added assert
+	to check if scale > 0. Trying to track down a divide by zero.
+
+2003-03-26  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/legend.py: Removed unnecessary LegendDialog class.
+	(LegendPanel): Removed _OnDock()/_OnUnDock() methods which are
+	now part of DockableWindow. 
+	(LegendPanel.DoOnSelChanged): Select the current layer in the
+	map.
+	(LegendTree._OnSelChanged): Call LegendPanel.DoOnSelChanged()
+	with the selected layer and/or group.
+
+2003-03-26  Jonathan Coles   <jonathan at intevation.de>
+
+	This putback contains the code for dockable windows. There is
+	no support in wxWindows as of this date for windows that can
+	attach themselves to other windows. 
+
+	The current model contains a DockableWindow which has a parent 
+	window for when it is detached and a dock window that it puts 
+	its contents in when it is docked. The contents of a DockableWindow 
+	must be a DockPanel. DockPanel itself derives from wxPanel.
+
+	* Thuban/Model/layer.py (Layer.ClassChanged): Send a LAYER_CHANGED
+	message, not a LAYER_LEGEND_CHANGED message.
+
+	* Thuban/Model/map.py (Map): Forward LAYER_CHANGED messages.
+
+	* Thuban/UI/classifier.py (Classifier.__init__): Use wxADJUST_MINSIZE
+	as one of the style properties for the fieldTypeText item to
+	be sure that its size is correct when the text changes.
+
+	* Thuban/UI/dock.py: New. Classes for the DockPanel and
+	DockableWindow.
+
+	* Thuban/UI/legend.py: Added some more buttons and made the
+	LegendPanel a DockPanel.
+
+	* Thuban/UI/mainwindow.py: Added sash windows to the main window
+	and supporting functions for manipulating the sashes.
+	(MainWindow.ShowLegend): Create a DockableWindow with the 
+	LegendPanel as the contents.
+
+	* Thuban/UI/messages.py: Added DOCKABLE_* messages
+
+	* Thuban/UI/view.py (MapCanves.SetMap): Listen for LAYER_CHANGED,
+	not LAYER_LEGEND_CHANGED, messages.
+
+2003-03-25  Jonathan Coles   <jonathan at intevation.de>
+
+	* setup.py: Added custom script bdist_rpm_build_script so that
+	when the rpm is built the path to wx-config is correct.
+
+	* setup.cfg: Added line saying to use the custom build script
+
+2003-03-20  Jonathan Coles   <jonathan at intevation.de>
+
+        Initial implementation of the Legend. 
+
+	* Thuban/UI/legend.py: New. Creates a window that shows the map's
+	Legend information and allows the user to add/modify classifications
+	and how the layers are drawn on the map.
+
+	* setup.py: New command 'build_docs' which currently uses
+	happydoc to generate html documentation for Thuban.
+
+	* Thuban/Model/classification.py (ClassGroup.GetDisplayText): New.
+	Returns a string which is appropriately describes the group.
+
+	* Thuban/Model/layer.py (Layer.SetClassification): Generate a
+	LAYER_CHANGED event instead of a LAYER_LEGEND_CHANGED event.
+
+	* Thuban/Model/map.py (Map): Rename messages and use new, more
+	specific, messages.
+
+	* Thuban/Model/messages.py: New message to indicate that a layer's
+	data has changed (LAYER_CHANGED). New map messages to indicate
+	when layers have been added/removed/changed or if the stacking order
+	of the layers has changed.
+
+	* Thuban/Model/session.py: Rename and use new messages.
+
+	* Thuban/UI/classifier.py: Remember if any changes have actually
+	been applied so that if the dialog is cancelled without an application
+	of changes we don't have to set a new classification.
+	(ClassDataPreviewer): Pulled out the window specific code and put it
+	ClassDataPreviewWindow. ClassDataPreviewer can then be used to draw
+	symbols on any DC.
+	
+	* Thuban/UI/mainwindow.py: New code to open the legend.
+
+	* Thuban/UI/view.py: Use new message names.
+
+2003-03-19  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/main.py (verify_versions): New. Checks the versions
+	of Python, wxPython, and some other libraries.
+
+	* extensions/thuban/wxproj.cpp (check_version): Checks the given
+	version against what wxproj was compiled with.
+	(check_version_gtk): If wxproj was compiled with gtk then check
+	the given version against the version of the gtk library 
+	currently being used.
+
+2003-03-14  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_command.py: Run the tests when the module is run as a
+	script
+
+2003-03-14  Bernhard Herzog  <bh at intevation.de>
+
+	Implement selection of multiple selected shapes in the same layer:
+
+	- Introduce a new class to hold the selection. This basically
+	  replaces the interactor which was nothing more than the
+	  selection anyway. A major difference is of course that the new
+	  selection class supports multiple selected shapes in one layer
+	
+	- Move the object that represents the selection from the
+	  application to the canvas. The canvas is a better place than the
+	  application because the selection represents which shapes and
+	  layer of the map displayed by the canvas are selected and
+	  affects how the map is drawn.
+
+	- Make the selection and its messages publicly available through
+	  the mainwindow.
+
+	- The non-modal dialogs do not get a reference to the interactor
+	  anymore as they can simply refer to their parent, the
+	  mainwindow, for the what the interactor had to offer.
+
+	* Thuban/UI/selection.py: New module with a class to represent the
+	selection.
+
+	* Thuban/UI/messages.py (SELECTED_TABLE, SELECTED_MAP): Remove
+	these unused messages
+
+	* Thuban/UI/application.py (ThubanApplication.OnInit)
+	(ThubanApplication.OnExit, ThubanApplication.SetSession): The
+	interactor is gone now.
+	(ThubanApplication.CreateMainWindow): There is no interactor
+	anymore so we pass None as the interactor argument for now for
+	compatibility.
+
+	* Thuban/UI/view.py (MapCanvas.delegated_messages)
+	(MapCanvas.Subscribe, MapCanvas.Unsubscribe): In Subscribe and
+	Unsubscribe, delegate messages according to the delegated_messages
+	class variable.
+	(MapCanvas.__getattr__, MapCanvas.delegated_methods): Get some
+	attributes from instance variables as described with the
+	delegated_methods class variable.
+	(MapCanvas.__init__): New instance variable selection holding the
+	current selection
+	(MapCanvas.do_redraw): Deal with multiple selected shapes. Simply
+	pass them on to the renderer
+	(MapCanvas.SetMap): Clear the selection when a different map is
+	selected.
+	(MapCanvas.shape_selected): Simple force a complete redraw. The
+	selection class now takes care of only issueing SHAPES_SELECTED
+	messages when the set of selected shapes actually does change.
+	(MapCanvas.SelectShapeAt): The selection is now managed in
+	self.selection
+
+	* Thuban/UI/mainwindow.py (MainWindow.delegated_messages)
+	(MainWindow.Subscribe, MainWindow.Unsubscribe): In Subscribe and
+	Unsubscribe, delegate messages according to the delegated_messages
+	class variable.
+	(MainWindow.delegated_methods, MainWindow.__getattr__): Get some
+	attributes from instance variables as described with the
+	delegated_methods class variable.
+	(MainWindow.__init__): The interactor as ivar is gone. The
+	parameter is still there for compatibility. The selection messages
+	now come from the canvas.
+	(MainWindow.current_layer, MainWindow.has_selected_layer):
+	Delegate to the the canvas.
+	(MainWindow.LayerShowTable, MainWindow.Classify)
+	(MainWindow.identify_view_on_demand): The dialogs don't need the
+	interactor parameter anymore.
+
+	* Thuban/UI/tableview.py (TableFrame.__init__)
+	(LayerTableFrame.__init__, LayerTableFrame.OnClose)
+	(LayerTableFrame.row_selected): The interactor is gone. It's job
+	from the dialog's point of view is now done by the mainwindow,
+	i.e. the parent. Subscribe to SHAPES_SELECTED instead
+	of SELECTED_SHAPE
+	
+	* Thuban/UI/dialogs.py (NonModalDialog.__init__): The interactor
+	is gone. It's job from the dialog's point of view is now done by
+	the mainwindow, i.e. the parent.
+	
+	* Thuban/UI/classifier.py (Classifier.__init__): The interactor is
+	gone. It's job from the dialog's point of view is now done by the
+	mainwindow, i.e. the parent.
+
+	* Thuban/UI/tree.py (SessionTreeView.__init__): The interactor is
+	gone. It's job from the dialog's point of view is now done by the
+	mainwindow, i.e. the parent.
+	(SessionTreeCtrl.__init__): New parameter mainwindow which is
+	stored as self.mainwindow. The mainwindow is need so that the tree
+	can still subscribe to the selection messages.
+	(SessionTreeCtrl.__init__, SessionTreeCtrl.unsubscribe_all)
+	(SessionTreeCtrl.update_tree, SessionTreeCtrl.OnSelChanged): The
+	selection is now accessible through the mainwindow. Subscribe to
+	SHAPES_SELECTED instead of SELECTED_SHAPE
+
+	* Thuban/UI/identifyview.py (IdentifyView.__init__): Use the
+	SHAPES_SELECTED message now.
+	(IdentifyView.selected_shape): Now subscribed to SHAPES_SELECTED,
+	so deal with multiple shapes
+	(IdentifyView.__init__, IdentifyView.OnClose): The interactor is
+	gone. It's job from the dialog's point of view is now done by the
+	mainwindow, i.e. the parent.
+
+	* Thuban/UI/controls.py (RecordListCtrl.fill_list): The second
+	parameter is now a list of shape ids.
+	(RecordTable.SetTable): The second parameter is now a list of
+	indices.
+
+	* Thuban/UI/renderer.py (ScreenRenderer.RenderMap): Rename the
+	selected_shape parameter and ivar to selected_shapes. It's now a
+	list of shape ids.
+	(MapRenderer.draw_label_layer): Deal with multiple selected
+	shapes. Rearrange the code a bit so that the setup and shape type
+	distinctions are only executed once.
+
+	* test/test_selection.py: Test cases for the selection class
+
+2003-03-11  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/load.py: Temporary fix so that the xml reader
+	doesn't cause Thuban to crash.
+
+	* Thuban/Model/layer.py: Handle the cyclic references between
+	a layer and its classification better, and be sure to disconnect
+	the classification from the layer when the layer is destroyed
+	so that we don't maintain a cyclic reference that may not be
+	garbage collected.
+
+	* Thuban/Model/classification.py: See comment for layer.py.
+
+2003-03-12  Jan-Oliver Wagner <jan at intevation.de>
+
+	* HOWTO-Release: New. Information on the steps for releasing
+	a new version of Thuban.
+
+2003-03-11  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classifier.py: Add normal border to SelectPropertiesDialog.
+	Use True instead of true.
+	(Classifier): Should have a single panel in which all the controls lie.
+
+	* Thuban/UI/proj4dialog.py: Add normal border.
+
+	* Thuban/UI/tree.py: Fixed problem with bad item images under Windows.
+
+	* Thuban/UI/mainwindow.py: Use True instead of true.
+
+	* setup.py: Update some definitions to use wxWindows2.4 files
+
+	* Data/iceland_sample_class.thuban: Fixed file so that the
+	field_type information is present.
+
+2003-03-10  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classifier.py (Classifier.__init__): Make the
+	field type label grow so that when the text changes the
+	size is updated correctly. This may be a wxWindows bug.
+
+2003-03-10  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/application.py: Changed SESSION_CHANGED to
+	SESSION_REPLACED.
+
+	* Thuban/UI/classifier.py: Wrap text with _(). 
+	(ClassGrid.CreateTable): Set dimensions and size hints here,
+	instead of in Reset, so we only set the size once.
+
+	* Thuban/UI/dialogs.py: Don't need Shutdown(); just use Close()!
+
+	* Thuban/UI/mainwindow.py (MainWindow.prepare_new_session):
+	Call Close() instead of Shutdown().
+
+	* Thuban/UI/messages.py: Changed SESSION_CHANGED to SESSION_REPLACED.
+
+	* Thuban/UI/tree.py: Changed SESSION_CHANGED to SESSION_REPLACED.
+	Go back to using OnClose() instead of Shutdown().
+
+2003-03-10  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classifier.py (Classifier): SelectField() needed
+	to know the old field index as well as the new one.
+
+2003-03-10  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classifier.py (Classifier): Use __SelectField()
+	to correctly set the table information and call this from
+	__init__ and from _OnFieldSelect so that all the information
+	is up to date when the dialog opens and when a field is changed.
+
+2003-03-10  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py (Classification): Don't use
+	layer's message function directly, use the ClassChanged() method
+	when then classification changes. SetField/SetFieldType/SetLayer
+	must keep the information about field name and field type in
+	sync when an owning layer is set or removed.
+
+	* Thuban/Model/layer.py: Added ClassChanged() so that the 
+	classification can tell the layer when its data has changed.
+	(Layer.SetClassification): Accepts None as an arguement to 
+	remove the current classification and correctly handles
+	adding a new classification.
+
+	* Thuban/Model/load.py: Comment out print statement
+
+	* test/test_classification.py, test/test_save.py: New and
+	improved tests.
+
+2003-03-07  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py: Implemented __copy__ and
+	__deepcopy__ for ClassGroup* and ClassGroupProperites so
+	they can easily be copied by the classifier dialog.
+	(ClassGroupProperites.__init__): The default line color should
+	have been Color.Black.
+
+	* Thuban/UI/classifier.py: Setting and Getting table values now
+	uses a consistent set of functions.
+	(Classifier): Now non-modal. Has field type label which changes
+	as the field changes. Keep track of buttons in a list so that
+	we can enable/disable the buttons when the None field is selected.
+	(SelectPropertiesDialog): Add buttons to make the colors transparent.
+
+	* Thuban/UI/dialogs.py (NonModalDialog.Shutdown): New method which
+	does what OnClose did, but can be called by the application to
+	close a window. Needed when a session changes, and we have to
+	close the classifier windows.
+
+	* Thuban/UI/mainwindow.py (MainWindow.prepare_new_session):
+	Shuts down open dialogs. Used when a new session is created
+	or a session is opened.
+	(MainWindow.SaveSession): Should only call application.SaveSession()
+	if we don't call SaveSessionAs first.
+	(MainWindow.Classify): Allow different classifier dialogs for
+	different layers.
+
+	* Thuban/UI/tree.py (SessionTreeView): Remove OnClose and let
+	the parent class handle it. Add Shutdown() to unsubscibe from
+	event notification and call the parent Shutdown(). This was
+	necessary so the application can close the tree window.
+
+2003-03-06  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py: Minor documentation changes,
+	Addition of __eq__ and __ne__ methods.
+	(Classification.SetLayer): prevent recursion between this method
+	and Layer.SetClassification().
+
+	* Thuban/Model/color.py: Addition of __eq__ and __ne__ methods.
+
+	* Thuban/Model/layer.py (SetClassification): prevent recursion 
+	between this method and Classification.SetLayer().
+
+	* test/test_classification.py, test/test_load.py,
+	test/test_session.py: Fixed and added tests for the classification
+	classes.
+
+2003-03-06  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/classifier.py (ClassGrid.__init__)
+	(ClassGrid.CreateTable): Move the SetSelectionMode call to
+	CreateTable because otherwise it triggers an assertion in
+	wxPython/wxGTK 2.4.
+
+2003-03-05  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/common.py: Move FIELDTYPE constants back to table.py.
+
+	* Thuban/Model/load.py: import FIELDTYPE constants from table.
+
+	* Thuban/UI/classifier.py: import FIELDTYPE constants from table.
+
+	* Thuban/Model/table.py: Put FIELDTYPE constants back.
+
+2003-03-05  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/UI/classifier.py: Added class documentation.
+	Fixed RTbug #1713, #1714. Added Move[Up|Down] buttons.
+	Store just the groups in the table and generate the other
+	column information when it is requested. Add "None" field
+	to pull-down to select no classification.
+
+	* Thuban/common.py: Moved FIELDTYPE constants from table.py 
+	(Str2Num): Only catch ValueError exceptions.
+
+	* Thuban/Model/classification.py: Class documentation. Renaming
+	of methods with Stroke to Line. Groups are stored in a single
+	list with the default as the first element. Groups are searched
+	in the order they appear in the list.
+
+	* Thuban/Model/color.py: Documentation.
+
+	* Thuban/Model/layer.py (Layer): Add GetFieldType to retreive
+	the kind of data represented by a field.
+
+	* Thuban/Model/load.py (ProcessSession): Use proper string
+	conversion function; fixes RTbug #1713.
+
+	* Thuban/Model/save.py (Saver): Store field type information.
+
+	* Thuban/Model/table.py: Put FIELDTYPE constants in common.py.
+	(Table): Add field_info_by_name() to retrieve field information
+	by specifying the field name, not the number.
+
+	* Thuban/UI/mainwindow.py: Function name changes.
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Only
+	get the layer classification once. Don't try to classify 
+	values when the field is None: just use the default properties.
+
+	* Thuban/UI/view.py: Function name changes.
+
+	* Doc/thuban.dtd: Add field_type attribute to a classification.
+
+2003-03-04  Bernhard Herzog  <bh at intevation.de>
+
+	* Doc/thuban.dtd: Use correct syntax for optional attributes. Make
+	the fill and stroke layer attributes optional with suitable
+	default values. Add the stroke_width layer attribute. Use correct
+	syntax for empty elements. Make the attribute list for labels
+	refer to the label element.
+
+2003-03-04  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (thuban_build_py.build): Add a comment about distutils in
+	Python 2.3 containing some of the functionality we implement in
+	setup.py ourselves.
+
+	* Thuban/UI/classifier.py (ClassGrid.__init__): Set the table
+	before the selection mode. Doing it the other way round triggers
+	an assertion in wxWindows.
+
+	* Thuban/Model/save.py (escape): Fix typo in doc-string
+
+	* Thuban/Model/classification.py: Remove unnecessary wxPython
+	import
+
+2003-03-04  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py (ClassGroupRange.GetProperties):
+	Parameter 'value' should default to None.
+
+	* Thuban/UI/mainwindow.py: Use Layer.GetClassification() since
+	the class attribute __classification is now private.
+
+	* Thuban/UI/classifier.py (ClassGrid): Moved OnCellDClick() from
+	Classifier to ClassGrid. Added support for removing selected rows,
+	which including code for keeping track of when cells are selected,
+	and deselected.
+	(ClassTable): Support for added/removing rows. Fixed a problem
+	with __ParseInput whereby it would not allow strings (only numbers)
+	to be entered.
+	(Classifier): Added button and supporting code for removing
+	selected rows.
+
+2003-02-27  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/common.py: Moved color conversion functions into
+	Thuban/UI/common.py.
+	(Str2Num): Now converts the float (not the string) to a long/int
+	so that an exception isn't thrown.
+
+	* Thuban/UI/common.py: Common functions used in several UI modules
+
+	* Thuban/Model/classification.py: Changed the class hierarchy
+	so that a Classification consists of Groups which return
+	Properties when a value matches a Group.
+
+	* Thuban/Model/layer.py: Fixed name resolution problem.
+
+	* Thuban/Model/load.py: Use new Classification and Group functions.
+
+	* Thuban/Model/save.py (Saver.write_attribs): Fixes a test case 
+	failure. 
+	(Saver.write_classification): Use new Classification and Group
+	functions.
+
+	* Thuban/UI/classifier.py: Changes to use new Classification and Group
+	functions. Fix to create a tuple with a single value instead of
+	simply returning the value.
+
+	* Thuban/UI/renderer.py: Use new Classification and Group functions.
+	Use common.py functions.
+
+	* Thuban/UI/tree.py: Use common.py functions.
+	
+	* test/test_classification.py: Use new Classification and Group
+	classes.
+
+2003-02-24  Jonathan Coles   <jonathan at intevation.de>
+
+	* Thuban/common.py (Color2wxColour, wxColour2Color): Conversion
+	functions from Thuban color objects to wxWindow colour objects.
+
+	* Thuban/Model/classification.py (Classification): Renamed
+	GetProperties() to GetClassData(). Used the new iterator
+	in TreeInfo().
+	(ClassIterator): Iterator implementation to iterate over the
+	ClassData objects in a classification object.
+
+	* Thuban/Model/save.py (Saver.write_classificaton): Uses
+	the new iterator to save the classification information.
+
+	* Thuban/UI/classifier.py (SelectPropertiesDialog): Support
+	for changing the stroke and fill colors and previewing the
+	changes.
+
+	* Thuban/UI/mainwindow.py (MainWindow.OpenSession, 
+	MainWindow.SaveSessionAs): Text string changes so the dialogs
+	have more meaningful titles.
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Change
+	Classification method name from GetProperties to GetClassData.
+
+	* Thuban/UI/view.py (MapCanvas.find_shape_at): Use method calls
+	instead of accessing now non-existent class variables.
+
+2003-02-24  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Remove
+	unneeded Shape() call. Rendering is substantially faster without
+	it and it avoids some problems with broken shape files.
+
+2003-02-20  Frank Koormann   <frank at intevation.de>
+
+	Force minimal size of identify and label dialogs. The autosizing 
+	looked too ugly.
+
+	* Thuban/UI/controls.py (RecordListCtrl): Set minimal width for columns.
+	* Thuban/UI/labeldialog.py (LabelDialog.dialog_layout): 
+	Set size of listctrl.
+	* Thuban/UI/identifyview.py (IdentifyView.__init__): 
+	Set size of dialog.
+
+2003-02-19  Jonathan Coles   <jonathan at intevation.de>
+
+	* test/test_classification.py, test/test_layer.py, 
+	test/test_load.py, test/test_map.py, test/test_session.py:
+	Updated the tests to use the new functions that are in the
+	respective classes.
+
+	* Thuban/Model/classification.py (Classification):
+	Uses the new ClassData* classes. Modification messages are 
+	passed up to the parent layer (if it exists).
+	(ClassData): New class to encapsulate the common data in each
+	classification property. 
+	(ClassDataDefault): Represents the Default class. data.
+	(ClassDataPoint): Represents a single class. data point
+	(ClassDataRange): Represents a class. range
+	(ClassDataMap): Represents a class. map (unused).
+
+	* Thuban/Model/color.py: Added Color.None to represent something
+	with no color. Color.Black represents the color black.
+	(NoColor): Helper class derived from Color to represent something
+	with no color.
+
+	* Thuban/Model/layer.py (Layer): Removed references to fill, stroke,
+	stroke_width attributes. Made the 'classification' attribute private.
+	New methods for setting/getting the classification.
+
+	* Thuban/Model/load.py (ProcessSession): Use new methods on Layer
+	to get the classifcation and use the new ClassData* classes to
+	hold the classification data. Use Str2Num to convert numbers 
+	properly.
+
+	* Thuban/Model/save.py (Saver): Use new Color and Classification
+	methods
+
+	* Thuban/UI/classifier.py (ClassGrid): New class to represent a
+	custom grid.
+	(ClassTable): Support for editing Values and Labels and for
+	changing what type (point or range) of data is stored in each
+	property based on how the user enters the data.
+	(Classifier): Support for saving the new classifications and
+	launching the dialog to edit a property.
+	(SelectPropertiesDialog): New class for editing the visual
+	properties of a classification (stroke color, width, and fill color) 
+	(ClassPreviewer): Took the Draw method from ClassRenderer and
+	made most of it into this new class. Intend to use this class in 
+	the SelectPropertiesDialog for previewing changes.
+
+	* Thuban/UI/renderer.py: Use new Color and Classification methods.
+
+	* Thuban/UI/tree.py: Formatting changes.
+
+	* Doc/thuban.dtd: Add 'label' element
+
+	* Thuban/common.py: New. Contains common routines used throughout
+	the code. 
+	(Str2Num): Takes a string and converts it to the "best" type of
+	number.
+
+2003-02-14  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py (MapCanvas.OnLeftUp): Make sure that the
+	dragging flag is always set to 0 even when the tool implementation
+	raises an exception
+
+2003-02-11  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/application.py (ThubanApplication.splash_screen): New
+	method to create a splash screen.
+	(ThubanApplication.ShowMainWindow): New. Show the main window.
+	Needed so the splash screen can display the mainwindow
+	(ThubanApplication.OnInit): Call the
+	new splash_screen method to determine whether the application
+	should display a splash screen. If it displays a splash screen do
+	not immediately show the main window.
+
+2003-02-11  Jonathan Coles  <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py: Added import line to fix
+	feature conflicts between running on python2.2 and python2.1.
+
+	* Thuban/UI/classifier.py (ClassTable): Didn't need to hang
+	onto the clinfo parameter, so removed the deepcopy().
+
+2003-02-10  Jonathan Coles  <jonathan at intevation.de>
+
+	* Thuban/Model/save.py (Saver.open_element, Saver.close_element):
+	Added element_open variable to track opening and closing of tags
+	so that tags that don't span more than one line are closed with
+	/> instead of </tag_name>. Use the GetDefault*() methods of
+	the Classification class.
+
+	* Thuban/Model/classification.py (Classificaton): Added set and
+	get methods for the default data. The class also takes a layer
+	reference so that modification messages can be sent. Fixed the
+	methods to use the new ClassData class.
+	(ClassData): New class to encapsulate the classification data
+
+	* Thuban/Model/layer.py (Layer): Remove the
+	Set[Fill|Stroke|StrokeWidth]() methods. Code should call the
+	SetDefault*() methods on the layer's classification object.
+	(Layer.__init__): Use the new SetDefault*() methods in the
+	Classification class.
+
+	* Thuban/Model/load.py (ProcessSession): Use the new ClassData
+	object instead of a dictionary.
+
+	* Thuban/UI/classifier.py (ClassRenderer): New class to
+	draw the classifications in the dialog box's table.
+	(Classifier): Modified to use the ClassRenderer class.
+
+	* Thuban/UI/mainwindow.py (MainWindow): Use the SetDefault*()
+	methods of the Classification class.
+
+	* Thuban/UI/renderer.py (MapRenderer): Use the Get*() methods
+	of the ClassData class.
+
+	* test/test_classification.py, test/test_layer.py,
+	test/test_map.py, test/test_session.py: Fix the tests to work
+	with the above code changes.
+
+2003-02-03  Jonathan Coles  <jonathan at intevation.de>
+
+	* Thuban/Model/classification.py (Classification): Added getNull()
+	to return the NullData reference
+
+	* Thuban/Model/layer.py (Layer.SetFill, Layer.SetStroke,
+	Layer.SetStrokeWidth): Modified these functions to change the
+	null data in the classification rather than keep these values
+	directly in the Layer class. Menu options to change these values
+	work again.
+
+2003-01-28  Jonathan Coles  <jonathan at intevation.de>
+
+	* Thuban/UI/classifier.py (Classifier): Resolved merging conflicts.
+	Fixed crashing problem on some systems. Dialog box shows
+	classification data.
+
+	* Thuban/UI/tree.py (SessionTreeCtrl.add_items): Handle drawing
+	Colors in the tree view.
+
+	* Thuban/Model/layer.py (Layer.TreeInfo): Added a call to build
+	the tree info for classifications. Commented out unnecessary lines.
+
+	* Thuban/Model/classification.py (Classification.TreeInfo): New
+	function to add information about the classification into the
+	tree view.
+
+2003-01-27  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/__init__.py (_): New.
+
+	* Thuban/Model/classification.py, Thuban/Model/extension.py,
+	Thuban/Model/layer.py, Thuban/Model/load.py, Thuban/Model/map.py,
+	Thuban/Model/session.py, Thuban/UI/application.py,
+	Thuban/UI/classifier.py, Thuban/UI/context.py, Thuban/UI/controls.py,
+	Thuban/UI/identifyview.py, Thuban/UI/labeldialog.py,
+	Thuban/UI/mainwindow.py, Thuban/UI/menu.py, Thuban/UI/proj4dialog.py,
+	Thuban/UI/renderer.py, Thuban/UI/tree.py, Thuban/Lib/connector.py,
+	Thuban/Lib/fileutil.py: Replace user string by _() for i18n.
+
+2003-01-27  Jonathan Coles  <jonathan at intevation.de>
+
+	* Thuban/Model/layer.py: Classification initialization calls.
+
+	* Thuban/Model/classification.py: Created class to encapsulate
+	a layer classification. Supports specific data points and
+	ranges.
+
+	* Thuban/Model/load.py: Added support for loading classification
+	information.
+
+	* Thuban/Model/save.py: Added support for saving classification
+	information.
+
+	* Thuban/UI/classifier.py: Initial class for a dialog box for
+	specifying classification information.
+
+	* Thuban/UI/mainwindows.py: Support for opening the classifier
+	dialog.
+
+	* Thuban/UI/renderer.py: Support for drawing a layer with the
+	classification information.
+
+	* Data/iceland_sample_class.thuban: iceland_sample with
+	classification data.
+
+	* test/test_classification: Tests for the Classification class.
+
+2002-12-09  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_command.py: New. Tests for the command classes.
+
+	* Thuban/UI/command.py (ToolCommand): New class for tool commands.
+	(Command.IsTool): New method to distinguish between command
+	switching tools and other commands.
+
+	* Thuban/UI/view.py (MapCanvas.SelectTool): New method to select
+	the tool to avoid direct assignments to instance variables
+	(MapCanvas.ZoomInTool, MapCanvas.ZoomOutTool, MapCanvas.PanTool)
+	(MapCanvas.IdentifyTool, MapCanvas.LabelTool): Use SelectTool to
+	change the tool
+
+	* Thuban/UI/mainwindow.py (MainWindow.update_command_ui): If an
+	active tool's command turns insensitive, disable the tool.
+	(_tool_command): Use the new ToolCommand class
+
+	* Examples/simple_extensions/simple_tool.py (simple_tool): Use the
+	SelectTool method to change the tool
+	(iconfile): Use the ToolCommand class
+
+2002-12-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/tree.py (SessionTreeCtrl.normalize_selection): Handle
+	the case of selected items that are not children of Layers or Maps
+	properly. Previously this bug would trigger an assertion in
+	wxWindows.
+
+2002-11-06  Frank Koormann  <franmk.koormann at intevation.de>
+
+	* Thuban/UI/mainwindow.py: Altered the order of tools in the
+	toolbar: First now are all navigation tools (Zoom In/Out, Pan,
+	Full Extent).
+
+2002-10-23  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (setup call): version now 0.1.3
+
+	* MANIFEST.in: Add the files in test/
+
+	* test/README: Add note about tests requiring the iceland data
+
+	* Thuban/UI/mainwindow.py (MainWindow.About): Add 2002 to
+	copyright notice.
+
+2002-10-18  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_map.py
+	(TestMapWithContents.test_projected_bounding_box): Use an explicit
+	epsilon.
+
+	* test/support.py (FloatComparisonMixin.assertFloatEqual)
+	(FloatComparisonMixin.assertFloatSeqEqual): give a more useful
+	message if the assertion fails and don't return the return value
+	of self.assert_. In assertFloatSeqEqual the return meant that not
+	all items of the sequence were compared.
+
+2002-09-20  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_fileutil.py: New. Test cases for Thuban.Lib.fileutil
+
+	* Thuban/Lib/fileutil.py: Fixup some whitespace and typos
+
+	* test/test_map.py (TestMapWithContents.test_tree_info): Create
+	the string with the bounding box on the fly because of platform
+	differences in the way %g is handled.
+
+	* test/test_layer.py (TestLayer.test_empty_layer): Create an empty
+	DBFfile too because Thuban layers can't yet cope missing DBF
+	files.
+
+2002-09-20  Bernhard Herzog  <bh at intevation.de>
+
+	* test/test_menu.py: Use initthuban instead of
+	add_thuban_dir_to_path to initialize Thuban.
+
+	* test/support.py (FloatComparisonMixin.assertFloatEqual): New.
+	Mixin class for float comparisons
+	(SubscriberMixin): New. Mixin class to test messages sent through
+	the Connector class
+
+	* test/README: Fix a typo and add the -v flag to the command for
+	individual tests
+
+	* test/test_session.py: New. Test cases for Thuban.Model.session
+
+	* test/test_proj.py: New. Test cases for Thuban.Model.proj
+
+	* test/test_map.py: New. Test cases for Thuban.Model.map
+
+	* test/test_layer.py: New. Test cases for Thuban.Model.layer
+
+	* test/test_label.py: New. Test cases for Thuban.Model.label
+
+	* test/test_connector.py: New. Test cases for Thuban.Lib.connector
+
+	* test/test_color.py: New. Test cases for Thuban.Model.color
+
+	* test/test_base.py: New. Test cases for Thuban.Model.base
+
+2002-09-13  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/session.py (Session.forwarded_channels): Forward
+	the CHANGED channel too.
+
+	* Thuban/Model/map.py (Map.forwarded_channels): Forward the
+	CHANGED channel too.
+	(Map.__init__): Call the Modifiable constructor as well.
+
+	* Thuban/Model/base.py (Modifiable.UnsetModified): Issue a CHANGED
+	event if the modified flag changes.
+	(Modifiable.changed): Tweak the doc-string.
+
+	* Thuban/UI/mainwindow.py (MainWindow.view_position_changed)
+	(MainWindow.set_position_text): Put the code that puts the text
+	with the mouse position into the status bar into the new method
+	set_position_text so that it can overwritten in derived classes.
+
+2002-09-12  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.RunMessageBox): Center the
+	message box on the main window.
+
+2002-09-11  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py: Underline the 'x' in "Exit" instead of
+	the 'E' because it's less likely to interfere with other menu
+	entries.
+	(MainWindow.build_menu): remove an incorrect comment.
+
+2002-09-10  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.Map): New.
+	(_tool_command): Add sensitive parameter
+	(_has_visible_map): Sensitivity callback to tools and other
+	commands that require a visible map. Use it in map_zoom_in_tool,
+	map_zoom_out_tool, map_pan_tool, map_identify_tool, map_label_tool
+	and map_full_extent
+
+2002-09-06  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.OnClose): Unsubscribe
+	VIEW_POSITION
+
+2002-09-04  Frank Koormann  <frank.koormann at intevation.de>
+
+	* Resources/Bitmaps/fullextent.xpm: Updated Icon (removed "potatoe")
+
+2002-09-02  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py: Get rid of the idle redraw. This is done by
+	wxWindows already and our implementation doesn't work correctly
+	with wxGTK 2.3:
+	(MapCanvas.__init__): Remove the instance variable
+	(MapCanvas.OnPaint): Always call do_redraw when there's a map to
+	be drawin
+	(MapCanvas.OnIdle): Removed.
+
+	* Thuban/UI/view.py (MapCanvas.unprojected_rect_around_point): Add
+	a parameter to determine the size of the rectangle.
+	(MapCanvas.find_shape_at): Create the box around the point on a
+	layer by layer basis and make the size depend on the shape type.
+	This solves a problem with the selection of point shapes at the
+	border of the layer's bounding box
+
+2002-08-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.CanRemoveLayer): New method
+	for the sensitivity  of remove layer.
+	(_can_remove_layer): New. Sensitivity callback for remove layer
+	(Command layer_remove): Use _can_remove_layer
+
+	* Thuban/Model/map.py (Map.CanRemoveLayer): New method to
+	determine whether a given layer can be deleted.
+
+	* Thuban/UI/view.py (MapCanvas.__init__, MapCanvas.OnPaint)
+	(MapCanvas.do_redraw): Get rid of the unused update_region
+	instance variable
+
+	* Thuban/UI/view.py: Add/update some doc-strings.
+
+	* test/: new subdirectory with a bunch of unit tests.
+
+	* test/README, test/test_table.py, test/test_save.py,
+	test/test_menu.py, test/test_load.py: Initial set of tests and
+	brief instructions on how to run them
+
+2002-08-29  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/renderer.py (ScreenRenderer.draw_shape_layer): Handle
+	arcs with multiple parts.
+
+	* Thuban/UI/view.py (ZoomInTool.MouseUp, ZoomOutTool.MouseUp):
+	Handle degenrate rectangles.
+
+	* Thuban/Model/table.py: Make writing records work correctly:
+	(Table.__init__): Keep track of whether the DBF is open for
+	writing
+	(Table.write_record): Open the DBF file for writing when necessary
+
+2002-08-27  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/table.py (Table.write_record, Table.__init__): Open
+	dbf files only for reading by default. Use a new writable dbf
+	object for writing.
+
+2002-08-26  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py: Refactor the context creation:
+	(MainWindow.Context): New method to return a context
+	(MainWindow.invoke_command, MainWindow.update_command_ui): Use the
+	new method
+
+	* Thuban/UI/tableview.py (TableGrid, LayerTableGrid): Split the
+	layer table specific code from TableGrid into LayerTableGrid
+	(TableFrame, LayerTableFrame): Split the layer table specific code
+	from TableFrame into LayerTableFrame
+	(LayerTableGrid.select_shape): Remove a debug print
+
+	* Thuban/UI/mainwindow.py (MainWindow.LayerShowTable): Use the
+	LayerTableFrame
+
+2002-08-23  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.__init__): Make sure we have an
+	absolute filename.
+
+2002-08-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/table.py (Table.write_record): New method to write
+	records.
+	(Table.__init__): Open the DBF file for writing too.
+
+	* Thuban/UI/controls.py (RecordTable.SetValue): Write the value
+	into the underlying table.
+
+	* extensions/shapelib/shapefil.h (DBFCommit),
+	extensions/shapelib/dbfopen.c (DBFCommit): New API function to
+	commit any changes made to the DBF file.
+
+	* Thuban/UI/mainwindow.py (make_check_current_tool)
+	(_tool_command): Put the code that generates the "checked"
+	callback into a separate function so that we can reuse it
+	elsewhere
+
+	* Thuban/Model/save.py (Saver): New class to handle serializing a
+	session into an XML file. The main reason to introduce a class is
+	that applications built on Thuban can derive from it so that they
+	can save additional information in a session file.
+	(save_session): Delegate almost all the work to the Saver class.
+	Rename the filename argument to file because it may be a file like
+	object now.
+
+	* Thuban/Model/load.py: Get rid of the Python 1.5.2 compatibility
+	code. Remove the little test code which would be executed when the
+	module is run as a script which didn't work anymore since it can't
+	import the other Thuban modules.
+	(ProcessSession, load_session): Refactor the ProcessSession to
+	have one method for each element start and end tag so that derived
+	classes can easily override the processing of individual tags.
+	Also, always parse with namespaces enabled because applications
+	built on top of Thuban will likely use namespaces if they extend
+	the session file format.
+
+2002-08-21  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (ThubanInstall.run): Don't repr install_lib_orig
+	because thubaninit_contents will do it for us.
+
+2002-08-16  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/mainwindow.py: menu item 'show session tree' now disable if
+	tree window already open
+
+2002-08-15  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.Destroy): Call the unboundd method
+	with self.
+
+	* Thuban/UI/view.py (MapCanvas.OnLeftUp): Only release the mouse
+	when we have actually captured it.
+
+	* Thuban/Model/layer.py (Layer.Destroy): New. Explicitly close the
+	shapefile and destroy the table.
+
+	* Thuban/Model/table.py (Table.Destroy): New. Close the DBF file.
+
+2002-08-14  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/controls.py (RecordTable.__init__): Remove the unused
+	instance variable columns
+	(RecordTable.GetTypeName): row and col may be negative in some
+	cases.
+
+	* setup.py (InstallLocal.initialize_options)
+	(InstallLocal.finalize_options, InstallLocal.user_options): New
+	option create-init-file to build a thubaninit.py when running
+	install_local
+	(InstallLocal.run): Create the thubaninit.py module when requested
+	(thubaninit_contents): Split the template into several parts and
+	create a new function thubaninit_contents that creates the
+	contents of a thubaninit module.
+	(ThubanInstall.run): Use the new function to create the thubaninit
+	module.
+
+2002-07-30  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/application.py (ThubanApplication.OnExit): Do some
+	cleanup.
+	(ThubanApplication.MainLoop): Extend to automatically call OnExit.
+
+	* Thuban/Model/session.py (Session.Destroy): Don't bypass the
+	direct base class' Destroy method.
+
+	* Thuban/Model/map.py (Map.ClearLayers): New method to delete all
+	layers.
+	(Map.Destroy): Destroy the label_layer as well and call the
+	inherited Desatroymethod first so that no more messages are
+	issued.
+	(Map.RaiseLayer, Map.LowerLayer): Only issue LAYERS_CHANGED
+	message if the stacking order actually has changed. Add
+	doc-strings.
+	(Map.BoundingBox): Correct the doc-string.
+	(Map.AddLayer, Map.RemoveLayer, Map.Layers, Map.HasLayers)
+	(Map.ProjectedBoundingBox, Map.SetProjection): Add doc-strings.
+
+	* Thuban/Model/label.py (LabelLayer.ClearLabels): New to delete
+	all labels.
+
+2002-07-29  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/map.py (Map.subscribe_layer_channels)
+	(Map.unsubscribe_layer_channels): Put the code that (un)subscribes
+	to a layer's channels into separate methods.
+	(Map.RemoveLayer, Map.AddLayer): Call the new methods
+	(Map.Destroy): Unsubscribe from a layer's channels before
+	destroying it.
+
+	* Thuban/UI/view.py (MapCanvas.find_shape_at): Change the
+	selected_layer parameter to searched_layer which is the layer to
+	search in.
+	(MapCanvas.SelectShapeAt): New parameter layer to restrict the
+	search to that layer. Return the selected layer and shape.
+
+	* Examples/simple_extensions/simple_tool.py (simple_tool): Fix a
+	typo
+
+2002-07-24  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/application.py (ThubanApplication.create_session):
+	Extend the doc string.
+	(ThubanApplication.subscribe_session)
+	(ThubanApplication.unsubscribe_session): New methods to
+	subscribe/unsubscribe to/from session channels.
+	(ThubanApplication.SetSession): Call the new methods here.
+	(ThubanApplication.maps_changed, ThubanApplication.set_map):
+	Renamed set_map to maps_changed. Its now a subscriber for
+	MAPS_CHANGED.
+
+	* Thuban/UI/view.py (ZoomOutTool.MouseUp): Use the correct
+	x-coordinate in case of simple clicks
+
+	* Thuban/Model/base.py (Modifiable.changed): Apply the args tuple,
+	don't pass it as a parameter
+
+	* Thuban/Model/session.py (Session.RemoveMap): New
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): Turn the initial
+	window size into a parameter.
+
+2002-07-23  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/menu.py (Menu.item_index): Also search for menus not
+	just commands.
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): Change the
+	parameter list a bit to allow setting the window title and the
+	initial message in the status bar. Update the callers.
+
+	* Thuban/UI/application.py (ThubanApplication.OnInit)
+	(ThubanApplication.CreateMainWindow): Put the mainwindow
+	instantiation into a separate method so that it can be overridden
+	by a subclass.
+
+2002-07-19  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/session.py: Issue a CHANGED message every time
+	another changed message is issued to make it easier to get
+	notified of changes.
+	(Session): Update the doc string
+	(Session.forward): Issue changed-events as CHANGED as well.
+	(Session.changed): Overwrite the inherited version to issue
+	CHANGED events as well.
+
+	* Thuban/UI/tree.py: We can now simply subscribe to the session's
+	CHANGED channel to be informed of changes.
+	(SessionTreeCtrl.session_channels): Not needed any longer.
+	(SessionTreeCtrl.unsubscribe_all, SessionTreeCtrl.session_changed):
+	Only have to (un)subscribe CHANGED
+
+	* Thuban/Model/map.py (Map.TreeInfo): Deal better with empty maps.
+
+	* Thuban/UI/main.py, Thuban/UI/__init__.py: Move the work-around
+	for the wxPython locale bug to __init__.py so that it's
+	automatically executed by anybody using UI code from Thuban.
+
+2002-07-18  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/main.py (main): app no longer needs to be global
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): Add application
+	as parameter and store it in an instance variable
+	(MainWindow.invoke_command, MainWindow.update_command_ui)
+	(MainWindow.save_modified_session, MainWindow.NewSession)
+	(MainWindow.OpenSession, MainWindow.SaveSession)
+	(MainWindow.SaveSessionAs, MainWindow.ShowSessionTree): Use self's
+	application object.
+
+	* Thuban/UI/application.py (ThubanApplication.OnInit): Instantiate
+	the main window with self.
+
+	* Thuban/UI/context.py: New module with the context class
+
+	* Thuban/UI/command.py (Command): Update doc string.
+
+	* Thuban/UI/mainwindow.py (MainWindow.invoke_command,
+	MainWindow.update_command_ui): Pass an instance of the context
+	class to the command's methods
+	(check_current_tool, call_method): Handle the new context
+	implementation
+
+	* Examples/simple_extensions/simple_tool.py (simple_tool,
+	check_simple_tool): Handle the new context implementation
+
+	* Examples/simple_extensions/simple_command.py (simple_command):
+	Handle the new context implementation. Update the comments about
+	the context.
+
+	* Thuban/UI/application.py (ThubanApplication.SetSession): Add
+	doc-string
+	(ThubanApplication.Session): New method to return the session
+	object
+
+	* Thuban/UI/tree.py (SessionTreeCtrl.update_tree): The
+	interactor's selected_layer may not be a layer of the current
+	session when the tree is updated while a new session is being set.
+
+2002-07-17  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/tree.py (color_string): Removed. No longer used.
+	(SessionTreeCtrl.update_tree, SessionTreeCtrl.add_items): Split
+	update_tree into update_tree and add_items. The tree now uses a
+	more generic way to display the contents of the tree.
+	(SessionTreeCtrl): Add a doc string explaining the TreeInfo method
+
+	* Thuban/Model/layer.py (Layer.TreeInfo),
+	Thuban/Model/extension.py (Extension.TreeInfo),
+	Thuban/Model/map.py (Map.TreeInfo),
+	Thuban/Model/session.py (Session.TreeInfo):
+	Add TreeInfo methods to implement the new tree view update scheme
+
+2002-07-16  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/application.py: Don't use "import from" for the
+	MainWindow. It can't always be resolved.
+	(ThubanApplication.OnInit): change reference to MainWindow
+	accordingly.
+
+	* Thuban/UI/menu.py (Menu.SetItems): New method to replace a menu
+	completely
+
+2002-07-10  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (create_init_module): New configurable variable whose
+	default depends on the platform we're running on.
+	(ThubanInstall.initialize_options): Initialize
+	self.create_init_module from the global create_init_module
+	(ThubanInstall.user_options): indictate that the options
+	create-init-module and init-module-dir have arguments.
+
+	* setup.py: In the setup call change the version number to include
+	cvs.
+
+	* MANIFEST.in: Add the files in Examples
+
+2002-07-09  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py: In the setup call, use the thuban homepage as the
+	value of the url parameter.
+
+	* Examples: New subdirectory for examples.
+
+	* Examples/simple_extensions/simple_tool.xpm,
+	Examples/simple_extensions/simple_tool.py,
+	Examples/simple_extensions/simple_command.py,
+	Examples/simple_extensions/README: Simple examples showing how to
+	add new commands and tools.
+
+	* setup.cfg (bdist_rpm): Add the default value for prefix and tell
+	bdist_rpm that we also have an install script.
+	(bdist_inno): Add 2002 to the copyright notice.
+
+	* setup.py: Create a file in python's site-packages directory to
+	make installation of Thuban as a library easier.
+	(ThubanInstall.user_options): Add two new options,
+	create-init-module and init-module-dir
+	(ThubanInstall.expand_with_pure_python_dirs): New method to expand
+	filenames for installation in the default directories.
+	(ThubanInstall.select_scheme, ThubanInstall.convert_paths): Extend
+	the inherited methods to capture some filenames before they're
+	transformed too much by distutils.
+	(ThubanInstall.run): Create the init module if requested.
+	(ThubanInstall.thuban_init_filename): New method to return the
+	full name of the init module.
+	(ThubanInstall.get_outputs): Append the filename of the init
+	module.
+
+2002-07-08  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (thuban_bdist_rpm): Extend this version of bdist_rpm to
+	handle the prefix properly which means that the default for the
+	installation prefix should be /usr for RPMs and /usr/local when
+	doing a normal source install.
+	(bdist_rpm_install_script): Script to override the default install
+	commands in the specfile generated by the bdist_rpm command.
+	(thuban_bdist_rpm.user_options): Add a prefix option
+	(thuban_bdist_rpm.initialize_options): Init the prefix option.
+	Create the script files for the spec files as empty files here
+	(thuban_bdist_rpm._make_spec_file): Override the inherited method
+	to fill the script files with content.
+
+	* Thuban/Model/save.py (relative_filename): Wrapper around
+	Thuban.Lib.fileutil.relative_filename that accepts an empty dir
+	argument. save_session now automatically uses this version,
+	solving a problem when saving to a relative filename.
+
+	* setup.py: In the setup call, make sure that the library
+	directories are under $prefix/lib not directly under $prefix.
+
+2002-06-20  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/Model/extension.py: new module to handle extension objects.
+	* Thuban/Model/messages.py: new messages for extensions.
+	* Thuban/Model/session.py (Session.Extensions, Session.HasExtensions,
+	Session.AddExtension): new for handling extensions.
+	Also some other minor changes to round up extension handling.
+	* Thuban/UI/tree.py (SessionTreeCrtl:update_tree): Added visualization
+	of Extension titles and title and names of its objects.
+
+2002-05-29  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.bind_command_events): Bind
+	the events for a command.
+	(MainWindow.add_toolbar_command, MainWindow.add_menu_command):
+	Call bind_command_events to bind the events. add_toolbar_command
+	can now bind events too so that it's possible to have commands
+	that are only available through the toolbar.
+	(MainWindow.init_ids): New instance variable events_bound to keep
+	track of for which commands events have been bound.
+
+2002-05-28  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/menu.py: New module to build and manage menus.
+
+	* Thuban/UI/mainwindow.py: Remove some unused imports.
+	(MainWindow.__init__, main_menu): move the definition of the main
+	menu from __init__ to the Menu instance main_menu.
+	(MainWindow.build_menu_bar, MainWindow.build_menu): New methods to
+	build the menu bar and sub-menus from a menu description.
+
+	* Thuban/UI/application.py (ThubanApplication.OnInit): Read the
+	startup file
+	(ThubanApplication.read_startup_files): New method to run
+	~/.thuban/thubanstart.py
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__, main_toolbar):
+	Move the toolbar definition to the Menu instance main_toolbar.
+	(MainWindow.build_toolbar): New method to build the toolbar
+	similar to the build_menu methods
+
+2002-05-23  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): Fix spelling of
+	layer_outline_color. Fix it in the definition of the command too.
+
+	* Thuban/UI/command.py (Command): Fix typo in doc string
+
+2002-05-22  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.RunMessageBox): Fix a typo
+	in the docstring
+
+2002-05-15  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.open_shapefile): Set bbox to None
+	when the shapefile is empty.
+	(Layer.BoundingBox, Layer.LatLongBoundingBox): Both methods may
+	now return None for empty shapefiles. Update doc-strings.
+
+	* Thuban/Model/map.py (Map.BoundingBox): Add doc-string. Deal with
+	the layer's bbox being None.
+
+	* Thuban/UI/tree.py (SessionTreeCtrl.update_tree): Deal with the
+	layer's bbox being None.
+
+	* Thuban/UI/view.py (MapCanvas.shape_selected): Only redraw when
+	necessary.
+	(MapCanvas.__init__): New instance variables, last_selected_layer
+	and last_selected_shape to determine how the selection has
+	changed.
+
+	* Thuban/UI/tableview.py (TableGrid.__init__): Do not call
+	AutoSizeColumns because it will cause a traversal of the entire
+	table which for large .dbf files will take a very long time.
+
+2002-05-14  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.open_shapefile): Choose a better
+	maximum depth for the tree than shapelib does by default.
+
+2002-05-10  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (py_modules): The shptree modules doesn't have a
+	wrapper, so don't include it in the py_modules
+
+2002-05-08  Bernhard Herzog  <bh at intevation.de>
+
+	* extensions/shapelib/shptree.c (compare_ints): Make arguments
+	const void * as in the qsort prototype
+	(SHPTreeFindLikelyShapes): Remove some unused variables.
+
+	* Thuban/UI/view.py (PanTool.MouseMove): Use the bitmap the view
+	maintains to redraw the window during a drag.
+	(MapCanvas.unprojected_rect_around_point): New method to determine
+	a small region around a point for hit-testing.
+	(MapCanvas.find_shape_at): Only test the shapes in a small region
+	around the point.
+
+	* setup.py: Increment the version to 0.1.2
+
+	* Thuban/UI/tree.py (SessionTreeCtrl.unsubscribe_all): Remove a
+	debug print and set session to None after unsubscribing
+
+2002-05-07  Bernhard Herzog  <bh at intevation.de>
+
+	* Data/iceland_sample.session, Data/iceland_sample.thuban: Rename
+	the file to have a .thuban extension.
+
+	* Thuban/UI/tree.py (session_channels): New class constant with
+	all the session channels to subscribe to to update the tree
+	(SessionTreeCtrl.session_changed): Remember the session so that we
+	can unsubscribe properly. Use the new class constant to
+	unsubscribe from the old session and subscribe to the new one.
+	(SessionTreeCtrl.unsubscribe_all): New method to unsubscribe all
+	subscriptions of the SessionTreeCtrl.
+	(SessionTreeView.OnClose): Call the tree's unsubscribe_all method.
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): Add the "Show
+	Session Tree" command to the file menu.
+
+	* Thuban/UI/view.py (MapCanvas.do_redraw): Pass the entire bitmap
+	as update_region to the renderer.
+
+	* Thuban/UI/renderer.py
+	(ScreenRenderer.layer_ids, ScreenRenderer.draw_shape_layer): The
+	update box is now directly a tuple, not a wxRect anymore.
+
+	* Thuban/Model/layer.py (Layer.ShapesInRegion): Remove some debug
+	prints.
+
+2002-05-07  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py: Add the shptree extension module. See
+	extensions/pyshapelib/ChangeLog for more details.
+
+	* extensions/shapelib/shpopen.c, extensions/shapelib/shapefil.h,
+	extensions/shapelib/dbfopen.c: Really update to the versions of
+	shapelib 1.2.9. For some reason it wasn't really done on
+	2002-04-11.
+
+	* extensions/shapelib/shptree.c: Modified version of shptree.c of
+	shapelib 1.2.9. The only real difference is the use of qsort
+	instead of a bubble sort implementation
+
+	* Thuban/Model/layer.py (Layer.__init__): New instance variable
+	shapetree to hold the shapelib quadtree for the shapefile
+	(Layer.open_shapefile): Create the quad tree.
+	(Layer.ShapesInRegion): New method to return the ids of shapes in
+	a given region using the quad tree.
+
+	* extensions/thuban/wxproj.cpp (project_points): Fix some typos in
+	comment
+	(draw_polygon_shape): Accept both arcs and polygons.
+	(initwxproj): Use the new PYSHAPELIB_IMPORT_API macro to import
+	the api.
+
+	* Thuban/UI/renderer.py (MapRenderer.layer_ids): New method to
+	return the shape ids to be rendered in a given layer.
+	(MapRenderer.draw_shape_layer): Call layer_ids to get the list of
+	ids. Use draw_polygon_shape to draw arc shapes as well.
+	(ScreenRenderer.RenderMap): New parameter for the rectangle that
+	has to be updated
+	(ScreenRenderer.layer_ids): Make use of the layer's quadtree by
+	calling it's ShapesInRegion method.
+
+	* Thuban/UI/view.py (MapCanvas.__init__): New instance variable
+	update_region for the update region.
+	(MapCanvas.OnPaint): Maintain the update region
+	(MapCanvas.do_redraw): Pass the bounding box of the update_region
+	to the renderer when drawing the bitmap. Reset the update_region.
+
+2002-05-03  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.SaveSessionAs,
+	MainWindow.OpenSession): Change the file extension of the session
+	files to .thuban
+
+	* Thuban/Model/session.py (Session.AddMap, forwarded_channels):
+	Move the map channels to be forwarded by the session into the
+	class constant with forwarded_channels. Also add
+	LAYER_PROJECTION_CHANGED and LAYER_VISIBILITY_CHANGED to
+	forwarded_channels
+
+	* Thuban/Model/base.py (Modifiable.changed): Fix doc-string (a
+	typo and some rewording).
+
+2002-05-02  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py: Keep the temporary bitmap used during drawing
+	around to speed up most redraws:
+	(MapCanvas.__init__): New instance variable bitmap which holds the
+	bitmap
+	(MapCanvas.do_redraw): Redraw self.bitmap if necessary. Use
+	self.bitmap to draw.
+	(MapCanvas.full_redraw): New method to force a full redraw
+	including the bitmap
+	(MapCanvas.SetMap): Subscribe full_redraw instead of redraw to
+	make sure the bitmap is redrawn.
+	(MapCanvas.projection_changed, MapCanvas.set_view_transform,
+	MapCanvas.shape_selected): Call full_redraw instead of readraw to
+	make sure the bitmap is redrawn.
+	(MapCanvas.OnSize): New method to handle size events so that the
+	bitmap can be redrawn.
+
+2002-04-29  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): Subscribe to the
+	canvas' VIEW_POSITION event
+	(MainWindow.view_position_changed): Handler for VIEW_POSITION.
+	Update the text in the status-bar accordingly.
+
+	* Thuban/UI/view.py (MapCanvas): Derive from Publisher as well
+	(MapCanvas.__del__): Implement because Publisher.__del__ has to be
+	called.
+	(MapCanvas.__init__): Bind EVT_LEAVE_WINDOW too. Initialize
+	current_position
+	(MapCanvas.set_current_position): New method to set
+	current_position. Issue a VIEW_POSITION event
+	(MapCanvas.CurrentPosition): New public method to return the value
+	of current_position. Should be called when the VIEW_POSITION event
+	is processed.
+	(MapCanvas.OnLeftDown, MapCanvas.OnLeftUp, MapCanvas.OnMotion):
+	Update the position.
+	(MapCanvas.OnLeaveWindow): Set the position to None.
+
+	* Thuban/UI/messages.py (VIEW_POSITION): New message for the
+	position in the statusbar
+
+2002-04-26  Frank Koormann <frank at intevation.de>
+
+	* Thuban/UI/mainwindow.py: AddLayer, Dialog title s/session/data
+
+2002-04-24  Frank Koormann <frank at intevation.de>
+
+	* Resources/Bitmaps/identify.xpm: shadow added
+
+	* Resources/Bitmaps/fullextent.xpm: new
+
+2002-04-22  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/tree.py (update_tree): added test for None on map bounding
+	box
+
+2002-04-21  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/proj4dialog.py (UTMProposeZoneDialog): new
+
+	* Thuban/UI/tree.py (update_tree): added added map extent
+
+	* Thuban/UI/mainwindow.py (_method_command): extended by parameter
+	icon; added map_full_extend as tool
+
+2002-04-19  Jan-Oliver Wagner <jan at intevation.de>
+
+	* Thuban/UI/mainwindow.py (SaveSession): launch save as dialog for
+	saving _new_ sessions
+
+	* Thuban/Model/session.py (create_empty_session): new session
+	don't have a filename (set to None)
+
+	* Thuban/UI/tree.py (update_tree): added filename and modified flag
+
+	* Thuban/Model/load.py (ProcessSession): convert projection
+	parameters from unicode to regular string
+
+	* Data/iceland_sample.session: Added UTM Zone 26 projection.
+
+2002-04-11  Bernhard Herzog  <bh at intevation.de>
+
+	* extensions/shapelib/shapefil.h, extensions/shapelib/shpopen.c,
+	extensions/shapelib/dbfopen.c: Update to the versions of shapelib
+	1.2.9
+
+	* setup.py (Lib.wxproj extension): Don't link shpopen.c and put
+	the pyshapelib directoy into the list of include dirs, so that
+	pyshapelib_api.h can be found.
+
+	* extensions/thuban/wxproj.cpp (pyshapelib_api): New variable that
+	holds the pyshapelib C-API
+	(draw_polygon_shape, point_in_polygon_shape, shape_centroid): Use
+	pyshapelib_api to access the shapelib functions.
+	(initwxproj): Import the c_api from the shapelib module and
+	initialize pyshapelib_api.
+
+2002-04-04  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (thuban_bdist_rpm.initialize_options): Use
+	initialize_options to create the scripts for the rpm.
+
+	* extensions/pyprojection/setup.py (PROJ4_PREFIX): Just use /
+
+2002-04-03  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py: Increment version to 0.1.1
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): Move the "Add
+	Layer" and "Remove Layer" commands from the layer menu to the map
+	menu
+
+2002-02-15  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/Model/layer.py (Layer.Shape): list append only takes one
+	argument (python <= 1.5.2 erroneously accepted multiuple
+	arguments)
+
+2002-02-04  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/identifyview.py (IdentifyGridCtrl): New class to use a
+	RecordGrid in the identifyview.
+	(IdentifyView.__init__): Use IdentifyGridCtrl instead of
+	IdentifyListCtrl. The grid allows editing of the values.
+
+	* Thuban/UI/controls.py (RecordTable, RecordGridCtrl): New classes
+	implementing a grid for a single row of a thuban table.
+
+	* Thuban/UI/view.py (MapCanvas.SelectShapeAt): Search through all
+	layers by default. Easier to use than the previous default of only
+	searching through the select layer which meant that if no layer
+	was selected, you couldn't select a shape.
+
+	* Thuban/UI/tableview.py (TableGrid.__init__): Fix typo
+
+	* Thuban/UI/renderer.py (MapRenderer.draw_shape_layer): Honour the
+	stroke_width attribute
+
+	* Thuban/Model/save.py (save_session): Write the new stroke_width
+	attribute
+
+	* Thuban/Model/load.py (ProcessSession.startElement): Read the
+	stroke_width attribute
+
+	* Thuban/Model/layer.py (Layer.__init__): New parameter and
+	instance variable stroke_width
+	(Layer.SetStrokeWidth): Set the stroke_width.
+
+2002-02-01  Bernhard Herzog  <bh at intevation.de>
+
+	* extensions/thuban/wxproj.cpp (project_points): Fix two
+	off-by-one errors in the last loop that joins the various parts
+	together.
+
+2002-01-14  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (data_dist.make_distribution): Fix some typos
+
+2001-09-18  Bernhard Herzog  <bh at intevation.de>
+
+	* README: Slight tweaking in preparation for the 0.1 release
+
+	* setup.cfg: Add section for sdist to create both tgz and zip
+	archives
+
+	* setup.py: increase version number to 0.1
+	(data_dist): New command class for data distribution
+
+2001-09-14  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/identifyview.py (IdentifyListCtrl.selected_shape):
+	Handle the case of no layer (i.e. layer is None) properly.
+
+	* Thuban/UI/proj4dialog.py (UTMDialog.__init__, Proj4Dialog.__init__):
+	Set the initial selection of the combo boxes to reflect the
+	projection we're starting with in a way that works on windows,
+	too.
+
+	* Thuban/Lib/connector.py (Connector.print_connections): Print the
+	puiblisher's ids in hex to make it easier to compare them to the
+	standard repr of python methods
+
+	* Thuban/Model/map.py (Map.Destroy): Unsubscribe the label_layer
+	messages
+
+2001-09-13  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/tree.py (SessionTreeCtrl.OnSelChanged): Make sure to
+	deselect the layer if no layer is selected
+
+	* Thuban/UI/view.py (MapCanvas.OnPaint): Only delay drawing to
+	idle time when there actually is something to draw. If there's
+	nothing to draw simply clear the window
+	(MapCanvas.do_redraw): Call dc.EndDrawing and add some comments.
+	(MapCanvas.SetMap): force a redraw in all cases because
+	FitMapToWindow doesn't always do it.
+	(MapCanvas.ZoomFactor): Add an optional parameter, center, to
+	specify the point to move into the center of the window
+	(ZoomOutTool.MouseUp, ZoomInTool.MouseUp): If the mouse wasn't
+	dragged, zoon in/out by a factor of 2
+	(MapCanvas.find_shape_at): Iterate backwards (i.e. with decreasing
+	index, i.e. reversed drawing order) so that objects appearing to
+	be in from of others are selected first. This is probably mostly
+	relevant for point shapes where the symbols used may overlap
+
+	* Thuban/Model/session.py (create_empty_session): Unset the
+	modified bit before returning it
+
+	* Thuban/UI/mainwindow.py (MainWindow.NewSession): Use
+	create_empty_session session to create the new, empty session.
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): Set the size of
+	the tool bitmaps.
+	(MainWindow.OnClose, MainWindow.save_modified_session): Separate
+	the code that asks whether the session should be saved into the
+	new method save_modified_session.
+	(MainWindow.OpenSession, MainWindow.NewSession): Use the new
+	method to save modified session here too.
+
+2001-09-11  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py (InnoIconItem): fix typo
+
+	(thuban_bdist_inno.run):
+	(bdist_inno.run): Move the decision not to create symlinks on
+	non-nt platforms to thuban_bdist_inno and do it unconditinally
+	since we never want to create the symlinks here
+
+2001-09-10  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.IdentifyTool): Popup the
+	identify view immediately
+
+	* Thuban/UI/controls.py: New file with two classes RecordListCtrl
+	and SelectableRecordListCtrl that implement the code shared by the
+	identify view and the label dialog
+
+	* Thuban/UI/identifyview.py (IdentifyListCtrl): Derive from the
+	new class RecordListCtrl
+
+	* Thuban/UI/labeldialog.py (LabelDialog.OnOK): Check whether the
+	return value of GetValue is None instead of using it as a boolean
+	directly so that Zero numbers are handled properly.
+	(LabelListCtrl): Derive from the new class
+	SelectableRecordListCtrl
+
+	* Thuban/UI/proj4dialog.py (Proj4Dialog.__init__):
+	(Proj4Dialog.dialogLayout): Make the window resizable and set the
+	size of the text control explicitly to make the sizers work on
+	both Windows and X.
+
+2001-09-07  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py (MapCanvas.find_shape_at):Add a new parameter
+	that can limit the search to the currently selected layer.
+	(MapCanvas.SelectShapeAt): Make sure that the currently selected
+	layer stays selected even when no shape is found
+	(MapCanvas.FitRectToWindow): If the rect has zero with or zero
+	height do nothing (avoids zero division errors)
+
+2001-09-06  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/tree.py (SessionTreeCtrl, SessionTreeView.__init__):
+	Correct the spelling of SessionTreeCtrl. dabbrev is too damn
+	convenient :-)
+	(SessionTreeCtrl.__init__, SessionTreeCtrl.update_tree): Introduce
+	a new instvar layer_to_item to map layers to tree items
+	(SessionTreeCtrl.layer_selected): Select the appropriate tree item
+	to match the current selection in the interactor
+
+	* Thuban/UI/interactor.py (Interactor.SelectedLayer):
+	(Interactor.HasSelectedLayer): New methods to query the current
+	selection
+
+	* Thuban/UI/mainwindow.py (MainWindow.current_layer):
+	(MainWindow.has_selected_layer): Simply call the appropriate
+	interactor method
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__):
+	(MainWindow.LayerShowTable):
+	(MainWindow.identify_view_on_demand): Store the interactor in an
+	instvar and use that reference instead of going through main.app
+
+	* Thuban/UI/mainwindow.py (MainWindow.ShowSessionTree):
+	* Thuban/UI/application.py (ThubanApplication.OnInit):
+	* Thuban/UI/main.py (main): Create the session tree view in main
+	with the new mainwindow method ShowSessionTree and not directly
+	the application's OnInit method
+
+	* Thuban/UI/tree.py (myTreeCtrlPanel):
+	(SessioinTreeCtrl): Rename to SessioinTreeCtrl and turn it into a
+	TreeCtrl isntead of a panel. This affects most method since we now
+	refer to self instead of self.tree
+	(SessionTreeView): New class implementing a non-modal dialog
+	showing the session tree.
+
+	* Thuban/UI/mainwindow.py (MainWindow.LayerShowTable): Pass the
+	layer to the tableview dialog.
+
+	* Thuban/UI/tableview.py: Add some doc-strings
+	(TableGrid):
+	(TableGrid.OnRangeSelect):
+	(TableGrid.OnSelectCell):
+	(TableFrame.__init__):
+	(TableFrame.row_selected):
+	Selecting rows in the grid view now updates the selected shapes
+	through the TableFrame. To achieve this we derive TableGrid from
+	Publisher and introduce the message type ROW_SELECTED which the
+	TableFrame subscribes to and which is issued by OnRangeSelect and
+	OnSelectCell
+
+	(DataTable.SelectRow): Removed because it's no longer needed in
+	the row/shape selection scheme
+
+	* Thuban/UI/dialogs.py: New file implementing common classes for
+	dialogs
+
+	* Thuban/UI/tableview.py (TableGrid.__init__): Don't subscribe to
+	the SELECTED_SHAPE message anymore. This is now handled by the
+	parent.
+	(TableGrid.select_shape): Only update the selection if the shape
+	is not None.
+	(TableFrame): Inherit from the new NonModalDialog class.
+	(TableFrame.__init__, TableFrame.select_shape): Handle the
+	SELECT_SHAPE message.
+	(TableFrame.OnClose): Extend the inherited method to unsubscribe
+	SELECT_SHAPE
+
+	* Thuban/UI/mainwindow.py (MainWindow.init_dialogs):
+	(MainWindow.add_dialog):
+	(MainWindow.dialog_open):
+	(MainWindow.remove_dialog):
+	(MainWindow.get_open_dialog): New methods to maintain a dictionary
+	of opened non-modal dialogs.
+
+	(MainWindow.__init__): Initialize the new non-modal dictionary
+	management code
+	(MainWindow.LayerShowTable): maintain separate dialogs for each
+	table using the non-modal dialog management code to only open a
+	view once for each table.
+
+	(MainWindow.IdentifyTool):
+	(MainWindow.__init__):
+	(MainWindow.identify_view_on_demand): Don't open the identify view
+	in IdentifyTool anymore. This will be done automatically by the
+	new method identify_view_on_demand which handles the
+	SELECTED_SHAPE message so that the identify view will be opened on
+	demand
+
+	* Thuban/UI/identifyview.py (IdentifyListCtrl.__init__): Remove
+	the interactor argument. The SELECTED_SHAPE message is now handled
+	by the parent.
+	(IdentifyView.__init__): Add the interactor argument so that we
+	can handle the SELECTED_SHAPE message here
+	(IdentifyView.selected_shape): New method to handle the
+	SELECTED_SHAPE messages
+
+	* Thuban/UI/identifyview.py (IdentifyView): Derive from the new
+	NonModalDialog class
+	(IdentifyView.OnClose): Extend the inherited version to
+	unsubscribe SELECT_SHAPE
+
+	* Thuban/Model/session.py (Session.UnsetModified): Remove debug prints
+
+2001-09-05  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/view.py (MapCanvas.__init__): New argument, interactor.
+
+	* Thuban/UI/mainwindow.py (MainWindow.__init__): New argument
+	interactor to pass through to the MapCanvas
+
+	* Thuban/UI/application.py (ThubanApplication.OnInit): Use the new
+	argument to the MainWindow constructor to get rid of the ugly hack
+	that made main.app available early just so that the mapcanvas
+	could access the interactor object.
+
+2001-09-04  Bernhard Herzog  <bh at intevation.de>
+
+	* Thuban/UI/mainwindow.py (MainWindow.RunMessageBox): New method
+	that runs a modal message box
+	(MainWindow.OnClose): Use the new method
+	(MainWindow.RemoveLayer): Just do nothing in case no layer is
+	selected. The command should be grayed out anyway, so there's no
+	need to pop up a message box.
+	(MainWindow.AddLayer): Pop up a message box with an error message
+	if the shape file can't be opened
+
+	* Thuban/Model/layer.py (Layer.__init__): Open the shapefile
+	immediately. This will cause an exception in case the file can't
+	be opened and we can display an appropriate message.
+
+	* MANIFEST.in: Add extensions/pyprojection/LICENSE
+
+	* setup.py (thuban_bdist_rpm): New class implementing a Thuban
+	specific bdist_rpm command.
+
+	* Thuban/UI/main.py: Catch ImportError exceptions when importing
+	the locale module because it may not be available on some
+	installations.
+
+	* extensions/pyprojection/LICENSE: Copy of the license text in
+	Projection.i. Having it in a separate file makes it easier to
+	refer to license text in e.g. RPMs
+
+2001-09-03  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py: use wx-config instead of wxgtk-config because it's
+	more generic
+
+	* setup.py (ThubanInstall.get_outputs): Add the symlink in
+	<prefix>/bin to the outputs
+	(ThubanInstall.link_file): New method to link files. We need this
+	because the standard copy_files refuses to link non-existing
+	files.
+	(ThubanInstall.run): Remove the leading install root from the
+	script filename if an install root was specified and use the new
+	link_file method
+
+	* Thuban/UI/mainwindow.py (MainWindow.AddLayer): Fit the map to
+	the window when the first layer is added to the map.
+
+	* setup.py (ThubanInstall.run): Honor the build root (self.root)
+	when linking thuban.py to <prefix>/bin
+
+2001-08-31  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py: In the setup call, the install parameters shouldn't
+	have trailing slashes because distutils on non-posix platforms
+	doesn't like that. The same applies to other directories like
+	"Resources/Bitmaps"
+
+	In the configuration section for nt, move the wxWindows directory
+	optins into the part clearly marked as editable.
+
+	(InstallLocal.initialize_options):
+	(InstallLocal.user_options): remove the currently unused debug
+	flag
+	(thuban_build_py.find_all_modules): Add this method so that it
+	works for our case of having packages and modules in one
+	distribution as well.
+	(ThubanInstall.initialize_options):
+	(ThubanInstall.finalize_options):
+	(ThubanInstall.user_options):
+	(ThubanInstall.boolean_options): Add new options, do-symlink and
+	extra files. Since these are the first ThubanInstall specific
+	options, override user_options and boolean_options
+	(ThubanInstall.run): Honor the new do-symlink and extra-files
+	options.
+	(ThubanInstall.get_outputs): Add to override the base-class's
+	version and add the extra-files to the outputs
+	(bdist_inno): New class for windows distributions with Inno Setup
+	(InnoIconItem): Helper class for bdist_inno
+	(thuban_bdist_inno): Thuban specific version of bdist_inno. Added
+	this together with the appropriate parameters, to the setup call.
+
+	* setup.cfg (bdist_inno): added new section for the inno setup
+	installer
+
+	* Thuban/UI/tree.py (myTreeCtrlPanel.__init__): New inst var
+	changing_selection to avoid recursive selection events when
+	modifying the selection in response to a selection event.
+	(myTreeCtrlPanel.normalize_selection): Set the new inst var when
+	changing the tree's selection.
+	(myTreeCtrlPanel.OnSelChanged): Only normalize the selection when
+	we're not being called indirectly from normalize_selection.
+
+	* Thuban/UI/mainwindow.py (MainWindow.update_command_ui): Call
+	event.Check only if the command is actuall checkable.
+	(MainWindow.__init__): Call the toolbar's Realize method to make
+	sure that the items are actually shown
+
+2001-08-28  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py: Fix some doc strings
+
+	* ChangeLog: started
+

Added: packages/thuban/branches/upstream/current/Doc/README
===================================================================
--- packages/thuban/branches/upstream/current/Doc/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,30 @@
+$Id: README 2728 2007-02-20 10:51:07Z bernhard $
+
+Currently, there is no explicit document on the implementation
+details but a UML description of the Model Module:
+	ThubanModul.xmi
+You can edit this file with Umbrello.
+
+Furthermore, you can generate class and method description
+automatically from the source code:
+
+pydoc coming with Python can be quite useful as a class browser.
+If you want to use it on Thuban, you need to give it the right
+paths so you can browse all of it.
+
+e.g. , the following starts pydoc as webbrowser on localhost:1234/
+        cd thuban
+        PYTHONPATH=./Lib:./test/ pydoc -p 1234
+
+A brief look into other documentation tools
+resulted in that the the best overview about them was coming with
+epydoc at:
+http://epydoc.sourceforge.net/relatedprojects.html
+
+epydoc seems to be very solid, because the author did a lot
+of reseach and decided for a very simple markup language.
+It might be surpassed one day by docutils which use the more
+complicated reStructured text as markup.
+
+As nice side contender is happydoc, because it does not import
+the python modules.

Added: packages/thuban/branches/upstream/current/Doc/ThubanModel.org.xmi
===================================================================
--- packages/thuban/branches/upstream/current/Doc/ThubanModel.org.xmi	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/ThubanModel.org.xmi	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1528 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XMI xmlns:UML="org.omg/standards/UML" verified="false" timestamp="" xmi.version="1.2" >
+ <XMI.header>
+  <XMI.documentation>
+   <XMI.exporter>umbrello uml modeller http://uml.sf.net</XMI.exporter>
+   <XMI.exporterVersion>1.2.0</XMI.exporterVersion>
+   <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
+  </XMI.documentation>
+  <XMI.model xmi.name="ThubanModel" href="/home/janschu/checka/ThubanModel.xmi" />
+  <XMI.metamodel xmi.name="UML" href="UML.xml" xmi.version="1.3" />
+ </XMI.header>
+ <XMI.content>
+  <docsettings viewid="174" documentation="" uniqueid="1356" />
+  <UML:Model>
+   <UML:DataType stereotype="datatype" visibility="public" xmi.id="175" name="int" />
+   <UML:DataType stereotype="datatype" visibility="public" xmi.id="176" name="char" />
+   <UML:DataType stereotype="datatype" visibility="public" xmi.id="177" name="bool" />
+   <UML:DataType stereotype="datatype" visibility="public" xmi.id="178" name="float" />
+   <UML:DataType stereotype="datatype" visibility="public" xmi.id="179" name="double" />
+   <UML:DataType stereotype="datatype" visibility="public" xmi.id="180" name="long" />
+   <UML:DataType stereotype="datatype" visibility="public" xmi.id="181" name="short" />
+   <UML:Package visibility="public" xmi.id="186" name="Model.base" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="194" name="Modifiable" >
+     <UML:Operation visibility="public" xmi.id="889" type="void" name="UnsetModified" />
+     <UML:Operation visibility="public" xmi.id="890" type="void" name="changed" >
+      <UML:Parameter visibility="public" xmi.id="1" value="None" type="string" name="channel" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="int" name="*.args" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="891" type="void" name="__init__" />
+     <UML:Operation visibility="public" xmi.id="892" type="bool" name="WasModified" />
+    </UML:Class>
+    <UML:Class stereotype="class" visibility="public" xmi.id="195" name="TitledObject" >
+     <UML:Operation visibility="public" xmi.id="919" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="920" type="string" name="Title" />
+     <UML:Operation visibility="public" xmi.id="921" type="void" name="SetTitle" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+    </UML:Class>
+   </UML:Package>
+   <UML:Package stereotype="Lib" visibility="public" xmi.id="188" name="Lib.connector" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="189" name="Publisher" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="196" name="Model.messages" />
+   <UML:Package visibility="public" xmi.id="198" name="Model.label" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="199" name="Label" >
+     <UML:Operation visibility="public" xmi.id="928" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="x" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="int" name="y" />
+      <UML:Parameter visibility="public" xmi.id="3" value="" type="string" name="text" />
+      <UML:Parameter visibility="public" xmi.id="4" value="" type="string" name="halign" />
+      <UML:Parameter visibility="public" xmi.id="5" value="" type="string" name="valign" />
+     </UML:Operation>
+    </UML:Class>
+    <UML:Class stereotype="class" visibility="public" xmi.id="200" name="LabelLayer" >
+     <UML:Operation visibility="public" xmi.id="923" type="void" name="AddLabel" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="x" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="int" name="y" />
+      <UML:Parameter visibility="public" xmi.id="3" value="" type="string" name="text" />
+      <UML:Parameter visibility="public" xmi.id="4" value="left" type="string" name="halign" />
+      <UML:Parameter visibility="public" xmi.id="5" value="center" type="string" name="valign" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="924" type="void" name="ClearLabels" />
+     <UML:Operation visibility="public" xmi.id="925" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="926" type="void" name="Labels" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Label" name="labels" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="927" type="void" name="RemoveLabels" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+     </UML:Operation>
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="207" name="Model.classification" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="208" name="ClassGroup" >
+     <UML:Operation visibility="public" xmi.id="1184" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1185" type="string" name="GetDisplayText" />
+     <UML:Operation visibility="public" xmi.id="1186" type="Label" name="GetLabel" />
+     <UML:Operation visibility="public" xmi.id="1187" type="ClassGroupProperties" name="GetProperties" />
+     <UML:Operation visibility="public" xmi.id="1188" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value=" " type="string" name="label" />
+      <UML:Parameter visibility="public" xmi.id="2" value="None" type="ClassGroupProperties" name="props" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1189" type="bool" name="IsVisible" />
+     <UML:Operation visibility="public" xmi.id="1190" type="bool" name="Matches" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="float" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1191" type="bool" name="__ne__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1192" type="string" name="__repr__" />
+     <UML:Operation visibility="public" xmi.id="1193" type="void" name="SetLabel" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="label" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1194" type="void" name="SetProperties" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroupProperties" name="prop" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1195" type="void" name="SetVisible" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="bool" name="visible" />
+     </UML:Operation>
+    </UML:Class>
+    <UML:Class stereotype="class" visibility="public" xmi.id="209" name="ClassGroupDefault" >
+     <UML:Operation visibility="public" xmi.id="1196" type="ClassGroupDefault" name="__copy__" />
+     <UML:Operation visibility="public" xmi.id="1197" type="ClassGroupDefault" name="__deepcopy__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="memo" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1198" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1199" type="string" name="GetDisplayText" />
+     <UML:Operation visibility="public" xmi.id="1200" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="None" type="ClassGroupProperties" name="props" />
+      <UML:Parameter visibility="public" xmi.id="2" value=" " type="string" name="label" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1201" type="bool" name="Matches" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="float" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1202" type="string" name="__repr__" />
+    </UML:Class>
+    <UML:Class stereotype="class" visibility="public" xmi.id="210" name="ClassGroupMap" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="211" name="ClassGroupProperties" >
+     <UML:Operation visibility="public" xmi.id="1241" type="ClassGroupProperties" name="__copy__" />
+     <UML:Operation visibility="public" xmi.id="1242" type="ClassGroupProperties" name="__deepcopy__" />
+     <UML:Operation visibility="public" xmi.id="1243" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroupProperties" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1244" type="Color" name="GetFill" />
+     <UML:Operation visibility="public" xmi.id="1245" type="Color" name="GetLineColor" />
+     <UML:Operation visibility="public" xmi.id="1246" type="int" name="GetLineWidth" />
+     <UML:Operation visibility="public" xmi.id="1247" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="None" type="ClassGroupProperties" name="props" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1248" type="bool" name="__ne__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroupProperties" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1249" type="string" name="__repr__" />
+     <UML:Operation visibility="public" xmi.id="1250" type="void" name="SetFill" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="fill" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1251" type="void" name="SetLineColor" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="color" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1252" type="void" name="SetLineWidth" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="lineWidth" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1253" type="void" name="SetProperties" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroupProperties" name="props" />
+     </UML:Operation>
+    </UML:Class>
+    <UML:Class stereotype="class" visibility="public" xmi.id="212" name="ClassGroupRange" >
+     <UML:Operation visibility="public" xmi.id="1209" type="ClassGroupRange" name="__copy__" />
+     <UML:Operation visibility="public" xmi.id="1210" type="ClassGroupRange" name="__deepcopy__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="mono" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1211" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClasGroup" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1212" type="string" name="GetDisplayText" />
+     <UML:Operation visibility="public" xmi.id="1213" type="int" name="GetMax" />
+     <UML:Operation visibility="public" xmi.id="1214" type="int" name="GetMin" />
+     <UML:Operation visibility="public" xmi.id="1215" type="string" name="GetRange" />
+     <UML:Operation visibility="public" xmi.id="1216" type="string" name="GetRangeTuple" />
+     <UML:Operation visibility="public" xmi.id="1217" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="(0, 1)" type="int2 or ClassGroupRange" name="_range" />
+      <UML:Parameter visibility="public" xmi.id="2" value="None" type="ClassGroupProperties" name="props" />
+      <UML:Parameter visibility="public" xmi.id="3" value=" " type="string" name="label" />
+      <UML:Parameter visibility="public" xmi.id="4" value="None" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1218" type="bool" name="Matches" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1219" type="string" name="__repr__" />
+     <UML:Operation visibility="public" xmi.id="1220" type="void" name="SetMax" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="max" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1221" type="void" name="SetMin" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="min" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1222" type="void" name="SetRange" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int2 or Range" name="_range" />
+     </UML:Operation>
+    </UML:Class>
+    <UML:Class stereotype="class" visibility="public" xmi.id="213" name="ClassGroupSingleton" >
+     <UML:Operation visibility="public" xmi.id="1232" type="ClassGroupSingleton" name="__copy__" />
+     <UML:Operation visibility="public" xmi.id="1233" type="ClassGroupSingleton" name="__deepcopy__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="mono" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1234" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1235" type="string" name="GetDisplayText" />
+     <UML:Operation visibility="public" xmi.id="1236" type="float" name="GetValue" />
+     <UML:Operation visibility="public" xmi.id="1237" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="0" type="float" name="value" />
+      <UML:Parameter visibility="public" xmi.id="2" value="None" type="ClassGroupProperties" name="props" />
+      <UML:Parameter visibility="public" xmi.id="3" value=" " type="string" name="label" />
+      <UML:Parameter visibility="public" xmi.id="4" value="None" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1238" type="bool" name="Matches" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="float" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1239" type="string" name="__repr__" />
+     <UML:Operation visibility="public" xmi.id="1240" type="void" name="SetValue" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="float" name="value" />
+     </UML:Operation>
+    </UML:Class>
+    <UML:Class stereotype="class" visibility="public" xmi.id="214" name="Classification" >
+     <UML:Operation visibility="public" xmi.id="1154" type="void" name="AppendGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="item" />
+     </UML:Operation>
+     <UML:Operation visibility="private" xmi.id="1155" type="string" name="build_color_item" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="color" />
+     </UML:Operation>
+     <UML:Operation visibility="private" xmi.id="1156" type="string" name="build_item" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="string" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1157" type="void" name="_clear_compiled_classification" />
+     <UML:Operation visibility="public" xmi.id="1158" type="void" name="_compile_classification" />
+     <UML:Operation visibility="public" xmi.id="1159" type="Classification" name="__deepcopy__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="memo" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1160" type="ClassGroup" name="FindGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1161" type="void" name="__getattr__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="attr" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1162" type="Color" name="GetDefaultFill" />
+     <UML:Operation visibility="public" xmi.id="1163" type="ClassGroupDefault" name="GetDefaultGroup" />
+     <UML:Operation visibility="public" xmi.id="1164" type="Color" name="GetDefaultLineColor" />
+     <UML:Operation visibility="public" xmi.id="1165" type="int" name="GetDefaultLineWidth" />
+     <UML:Operation visibility="public" xmi.id="1166" type="ClassGroup" name="GetGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1167" type="int" name="GetNumGroups" />
+     <UML:Operation visibility="public" xmi.id="1168" type="ClassGroupProperties" name="GetProperties" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1169" type="void" name="__init__" />
+     <UML:Operation visibility="public" xmi.id="1170" type="void" name="InsertGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1171" type="ClassIterator" name="__iter__" />
+     <UML:Operation visibility="public" xmi.id="1172" type="void" name="RemoveGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1173" type="void" name="ReplaceGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1174" type="void" name="__SendNotification" />
+     <UML:Operation visibility="public" xmi.id="1175" type="void" name="SetDefaultFill" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="fill" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1177" type="void" name="SetDefaultGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1178" type="void" name="SetDefaultLineColor" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="color" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1179" type="void" name="SetDefaultLineWidth" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="lineWidth" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1180" type="string[]" name="TreeInfo" />
+    </UML:Class>
+    <UML:Class stereotype="class" visibility="public" xmi.id="215" name="ClassIterator" >
+     <UML:Operation visibility="public" xmi.id="1181" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup[]" name="data" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1182" type="ClassIterator" name="__iter__" />
+     <UML:Operation visibility="public" xmi.id="1183" type="ClassGroup" name="next" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="216" name="Model.color" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="217" name="Color" >
+     <UML:Operation visibility="public" xmi.id="1258" type="void" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1259" type="string" name="hex" />
+     <UML:Operation visibility="public" xmi.id="1260" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="red" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="int" name="green" />
+      <UML:Parameter visibility="public" xmi.id="3" value="" type="int" name="blue" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1261" type="bool" name="__ne__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1262" type="string" name="__repr__" />
+    </UML:Class>
+    <UML:Class stereotype="class" comment="An object which represents no color." visibility="private" xmi.id="218" name="_Transparent" >
+     <UML:Operation visibility="public" xmi.id="1254" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Object" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1255" type="string" name="hex" />
+     <UML:Operation visibility="public" xmi.id="1256" type="bool" name="__ne__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Object" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1257" type="string" name="__repr__" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="219" name="Model.extension" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="220" name="Extension" >
+     <UML:Operation visibility="public" xmi.id="1143" type="void" name="AddObject" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ObjectfromExtension" name="object" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1144" type="void" name="Destroy" />
+     <UML:Operation visibility="public" xmi.id="1145" type="ObjectfromExtension" name="FindObject" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1146" type="void" name="forward" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="*.args" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1147" type="bool" name="HasObjects" />
+     <UML:Operation visibility="public" xmi.id="1148" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1149" type="ObjectfromExtension[]" name="Objects" />
+     <UML:Operation visibility="public" xmi.id="1150" type="void" name="RemoveObject" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ObjectfromExtension" name="object" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1151" type="string[]" name="TreeInfo" />
+     <UML:Operation visibility="public" xmi.id="1152" type="void" name="UnsetModified" />
+     <UML:Operation visibility="public" xmi.id="1153" type="int" name="WasModified" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="224" name="Model.layer" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="225" name="BaseLayer" >
+     <UML:Operation visibility="public" xmi.id="931" type="Projection" name="GetProjection" />
+     <UML:Operation visibility="public" xmi.id="932" type="bool" name="HasClassification" />
+     <UML:Operation visibility="public" xmi.id="933" type="bool" name="HasShapes" />
+     <UML:Operation visibility="public" xmi.id="934" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+      <UML:Parameter visibility="public" xmi.id="2" value="True" type="bool" name="visible" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="Projection" name="projection" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="935" type="void" name="SetProjection" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Projection" name="projection" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="936" type="void" name="SetVisible" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="bool" name="visible" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="937" type="bool" name="Visible" />
+    </UML:Class>
+    <UML:Class stereotype="class" visibility="public" xmi.id="226" name="Layer" >
+     <UML:Operation visibility="public" xmi.id="943" type="tuple(int,int,int,int)" name="BoundingBox" />
+     <UML:Operation visibility="public" xmi.id="944" type="void" name="_classification_changed" />
+     <UML:Operation visibility="public" xmi.id="945" type="tuple(int,int,int,int)" name="ClipBoundingBox" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="tuple(int,int,int,int)" name="bbox" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="946" type="void" name="Destroy" />
+     <UML:Operation visibility="public" xmi.id="947" type="string" name="GetClassificationColumn" />
+     <UML:Operation visibility="public" xmi.id="948" type="Classification" name="GetClassification" />
+     <UML:Operation visibility="public" xmi.id="949" type="Column.type" name="GetFieldType" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="fieldName" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="950" type="bool" name="HasClassification" />
+     <UML:Operation visibility="public" xmi.id="951" type="bool" name="HasShapes" />
+     <UML:Operation visibility="public" xmi.id="952" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="Shape data" name="data" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="Projection" name="projection" />
+      <UML:Parameter visibility="public" xmi.id="4" value="Transparent" type="Color" name="fill" />
+      <UML:Parameter visibility="public" xmi.id="5" value="Black" type="Color" name="stroke" />
+      <UML:Parameter visibility="public" xmi.id="6" value="1" type="int" name="lineWidth" />
+      <UML:Parameter visibility="public" xmi.id="7" value="True" type="bool" name="visible" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="953" type="bbox" name="LatLongBoundingBox" />
+     <UML:Operation visibility="public" xmi.id="954" type="int" name="NumShapes" />
+     <UML:Operation visibility="public" xmi.id="955" type="void" name="SetClassificationColumn" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="column" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="956" type="void" name="SetClassification" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Classification" name="clazz" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="957" type="void" name="SetShapeStore" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="shapestore" name="store" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="958" type="tuple(int,int,int,int)" name="ShapesBoundingBox" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="shapes" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="959" type="Shape" name="Shapes" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="960" type="Shapes" name="ShapesInRegion" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="tuple(int,int,int,int)" name="bbox" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="962" type="shapestore" name="ShapeStore" />
+     <UML:Operation visibility="public" xmi.id="963" type="constanten" name="ShapeType" />
+     <UML:Operation visibility="public" xmi.id="964" type="string()" name="TreeInfo" />
+    </UML:Class>
+    <UML:Class stereotype="class" visibility="public" xmi.id="227" name="RasterLayer" >
+     <UML:Operation visibility="public" xmi.id="938" type="tuple(int,int,int,int))" name="BoundingBox" />
+     <UML:Operation visibility="public" xmi.id="939" type="string" name="GetImageFilename" />
+     <UML:Operation visibility="public" xmi.id="940" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="string" name="filename" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="Projection" name="projection" />
+      <UML:Parameter visibility="public" xmi.id="4" value="True" type="bool" name="visible" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="941" type="tuple(int,int,int,int)" name="LatLongBox" />
+     <UML:Operation visibility="public" xmi.id="942" type="tuple(string, array(string))" name="TreeInfo" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="232" name="Model.map" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="233" name="Map" >
+     <UML:Operation visibility="public" xmi.id="1060" type="void" name="AddLayer" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1061" type="int4" name="BoundingBox" />
+     <UML:Operation visibility="public" xmi.id="1062" type="int" name="CanRemoveLayer" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1063" type="void" name="ClearLayers" />
+     <UML:Operation visibility="public" xmi.id="1064" type="void" name="Destroy" />
+     <UML:Operation visibility="public" xmi.id="1065" type="void" name="forward" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="*args" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1066" type="Projection" name="GetProjection" />
+     <UML:Operation visibility="public" xmi.id="1067" type="bool" name="HasLayers" />
+     <UML:Operation visibility="public" xmi.id="1068" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+      <UML:Parameter visibility="public" xmi.id="2" value="None" type="Projection" name="projection" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1069" type="LabelLayer" name="LabelLayer" />
+     <UML:Operation visibility="public" xmi.id="1070" type="Layer[]" name="Layers" />
+     <UML:Operation visibility="public" xmi.id="1071" type="void" name="LowerLayer" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1072" type="void" name="MoveLayerToBottom" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1073" type="void" name="MoveLayerToTop" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1074" type="int4" name="ProjectedBoundingBox" />
+     <UML:Operation visibility="public" xmi.id="1075" type="void" name="RaiseLayer" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1076" type="void" name="RemoveLayer" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1077" type="void" name="SetProjection" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Projection" name="projection" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1078" type="void" name="subscribe_layer_channels" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1079" type="void" name="TreeInfo" />
+     <UML:Operation visibility="public" xmi.id="1080" type="void" name="UnsetModified" />
+     <UML:Operation visibility="public" xmi.id="1081" type="void" name="unsubscribe_layer_channels" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1082" type="string()" name="WasModified" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="236" name="Model.proj" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="237" name="BaseProjection" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="238" name="ProjFile" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="733" name="Projection" >
+     <UML:Operation visibility="public" xmi.id="991" type="string" name="EPSGCode" />
+     <UML:Operation visibility="public" xmi.id="992" type="int()" name="ForwardBBox" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int()" name="bbox" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="993" type="string[]" name="GetAllParameters" />
+     <UML:Operation visibility="public" xmi.id="994" type="string" name="GetName" />
+     <UML:Operation visibility="public" xmi.id="995" type="string" name="GetParameter" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="param" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="996" type="int" name="GetProjectedUnits" />
+     <UML:Operation visibility="public" xmi.id="997" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="stinr[]" name="params" />
+      <UML:Parameter visibility="public" xmi.id="2" value="None" type="string" name="name" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="string" name="epsg" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="998" type="int()" name="InverseBBox" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int()" name="bbox" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="999" type="string" name="Label" />
+     <UML:Operation visibility="public" xmi.id="1000" type="string" name="__repr__" />
+     <UML:Operation visibility="public" xmi.id="1001" type="int(4)" name="_transform_bbox" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Trafo" name="trafo" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="int(4)" name="bbox" />
+     </UML:Operation>
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="239" name="Model.session" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="240" name="AutoRemoveDir" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="241" name="AutoRemoveFile" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="242" name="Session" >
+     <UML:Operation visibility="public" xmi.id="1083" type="void" name="AddDBConnection" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="PostGISConnection" name="dbconn" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1084" type="void" name="AddExtension" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Extension" name="extension" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1085" type="void" name="AddMap" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Map" name="map" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1086" type="void" name="AddShapeStore" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ShapefileStore" name="shapestore" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1087" type="void" name="_add_shapestore" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ShapefileStore" name="store" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1088" type="void" name="AddTable" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="AutoTransientTable" name="table" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1089" type="int" name="CanRemoveDBConnection" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="PostGISConnection" name="dbconn" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1090" type="void" name="changed" >
+      <UML:Parameter visibility="public" xmi.id="1" value="None" type="" name="channel" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="" name="*args" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1091" type="void" name="_clean_weak_store_refs" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="weakref" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1092" type="data containers" name="DataContainers" />
+     <UML:Operation visibility="public" xmi.id="1093" type="PostGISConnection" name="DBConnections" />
+     <UML:Operation visibility="public" xmi.id="1094" type="void" name="Destroy" />
+     <UML:Operation visibility="public" xmi.id="1095" type="Extension[]" name="Extensions" />
+     <UML:Operation visibility="public" xmi.id="1096" type="void" name="forward" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="*args" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1097" type="int" name="HasDBConnections" />
+     <UML:Operation visibility="public" xmi.id="1098" type="int" name="HasExtensions" />
+     <UML:Operation visibility="public" xmi.id="1099" type="int" name="HasMaps" />
+     <UML:Operation visibility="public" xmi.id="1100" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1101" type="Map[]" name="Maps" />
+     <UML:Operation visibility="public" xmi.id="1102" type="ShapefileStore" name="OpenDBShapeStore" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="PostGISConnection" name="db" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="string" name="tablename" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="string" name="id_column" />
+      <UML:Parameter visibility="public" xmi.id="4" value="None" type="string" name="geometry_column" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1103" type="ShapefileStore" name="OpenShapefile" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="filename" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1104" type="DBFTable" name="OpenTableFile" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="filename" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1105" type="void" name="RemoveDBConnection" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="PostGISConnection" name="dbconn" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1106" type="void" name="RemoveMap" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Map" name="map" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1107" type="void" name="RemoveTable" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="*Table" name="table" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1108" type="void" name="SetFilename" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="filename" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1109" type="ShapefileStore[]" name="ShapeStores" />
+     <UML:Operation visibility="public" xmi.id="1110" type="*Tables[]" name="Tables" />
+     <UML:Operation visibility="public" xmi.id="1111" type="string" name="temp_directory" />
+     <UML:Operation visibility="public" xmi.id="1112" type="TransientDatabase" name="TransientDB" />
+     <UML:Operation visibility="public" xmi.id="1113" type="string[]" name="TreeInfo" />
+     <UML:Operation visibility="public" xmi.id="1114" type="*Tables[]" name="UnreferencedTables" />
+     <UML:Operation visibility="public" xmi.id="1115" type="void" name="UnsetModified" />
+     <UML:Operation visibility="public" xmi.id="1116" type="int" name="WasModified" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="261" name="Model.range" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="262" name="Range" >
+     <UML:Operation visibility="public" xmi.id="1223" type="bool" name="__contains__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1224" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Range" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1225" type="string" name="_float2string" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="float" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1226" type="string4" name="GetRange" />
+     <UML:Operation visibility="public" xmi.id="1227" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="None" type="string" name="range" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1228" type="void" name="__ne__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Range" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1229" type="void" name="_SetRange" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="range" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1230" type="string" name="string" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="tuple(string,int,int,string)" name="range" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1231" type="string" name="__str__" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="264" name="Model.data" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="265" name="DerivedShapeStore" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="266" name="ShapefileShape" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="267" name="ShapefileStore" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="268" name="ShapeTable" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="269" name="Model.load" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="270" name="AttrDesc" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="271" name="LoadCancelled" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="272" name="LoadError" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="273" name="SessionLoader" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="280" name="Model.classgen" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="281" name="CustomRamp" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="282" name="FixedRamp" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="283" name="HotToColdRamp" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="284" name="MonochromaticRamp" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="285" name="Model.postgisdb" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="286" name="ConnectionError" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="287" name="PostGISColumn" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="288" name="PostGISConnection" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="289" name="PostGISShape" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="291" name="PostGISTable" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="825" name="PostGISShapeStore" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="292" name="Model.resource" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="293" name="ProjFileReader" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="294" name="ProjFileSaver" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="295" name="Model.save" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="296" name="SessionSaver" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="297" name="Model.scalebar" />
+   <UML:Package visibility="public" xmi.id="298" name="Model.table" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="299" name="DBFColumn" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="300" name="DBFTable" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="301" name="MemoryColumn" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="302" name="MemoryTable" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="303" name="Model.transientdb" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="304" name="AutoTransientTable" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="305" name="ColiumnReference" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="306" name="TransientDatabase" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="307" name="TransientJoinedTable" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="308" name="TransientTableBase" />
+    <UML:Class stereotype="class" visibility="public" xmi.id="309" name="TransientTable" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="310" name="Model.wellknowntext" />
+   <UML:Package visibility="public" xmi.id="311" name="Model.xmlreader" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="313" name="XMLReader" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="312" name="Model.xmlwriter" >
+    <UML:Class stereotype="class" visibility="public" xmi.id="314" name="XMLWriter" />
+   </UML:Package>
+   <UML:Association visibility="public" xmi.id="201" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="200" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="195" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="202" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="194" />
+     <UML:AssociationEndRole visibility="public" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="203" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="200" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="206" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="194" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="189" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="221" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="220" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="195" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="222" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="220" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="228" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="225" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="229" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="225" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="195" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="230" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="226" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="225" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="231" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="227" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="225" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="234" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="233" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="235" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="233" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="195" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="243" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="242" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="244" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="242" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="195" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="251" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="210" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="208" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="252" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="212" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="208" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="253" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="213" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="208" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="254" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="214" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="189" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="263" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="218" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="217" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="316" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="195" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="189" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="318" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="233" />
+     <UML:AssociationEndRole visibility="public" type="233" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="341" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="227" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="226" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Generalization child="194" visibility="public" xmi.id="600" parent="189" />
+   <UML:Generalization child="200" visibility="public" xmi.id="602" parent="195" />
+   <UML:Generalization child="200" visibility="public" xmi.id="603" parent="194" />
+   <UML:Association visibility="public" xmi.id="605" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="200" />
+     <UML:AssociationEndRole visibility="public" type="199" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Generalization child="225" visibility="public" xmi.id="615" parent="195" />
+   <UML:Generalization child="225" visibility="public" xmi.id="616" parent="194" />
+   <UML:Generalization child="220" visibility="public" xmi.id="625" parent="194" />
+   <UML:Generalization child="220" visibility="public" xmi.id="626" parent="195" />
+   <UML:Generalization child="233" visibility="public" xmi.id="645" parent="194" />
+   <UML:Generalization child="233" visibility="public" xmi.id="646" parent="195" />
+   <UML:Generalization child="242" visibility="public" xmi.id="655" parent="194" />
+   <UML:Generalization child="242" visibility="public" xmi.id="656" parent="195" />
+   <UML:Generalization child="227" visibility="public" xmi.id="669" parent="225" />
+   <UML:Generalization child="226" visibility="public" xmi.id="670" parent="225" />
+   <UML:Generalization child="214" visibility="public" xmi.id="679" parent="189" />
+   <UML:Association visibility="public" xmi.id="681" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="214" />
+     <UML:AssociationEndRole visibility="public" type="208" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Generalization child="209" visibility="public" xmi.id="695" parent="208" />
+   <UML:Generalization child="212" visibility="public" xmi.id="705" parent="208" />
+   <UML:Generalization child="213" visibility="public" xmi.id="706" parent="208" />
+   <UML:Association visibility="public" xmi.id="708" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="226" />
+     <UML:AssociationEndRole visibility="public" type="214" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="715" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="208" />
+     <UML:AssociationEndRole visibility="public" type="211" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="716" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="211" />
+     <UML:AssociationEndRole visibility="public" type="217" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="721" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="composite" type="242" />
+     <UML:AssociationEndRole visibility="public" type="233" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="722" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="242" />
+     <UML:AssociationEndRole visibility="public" type="220" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="731" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="composite" type="233" />
+     <UML:AssociationEndRole visibility="public" type="226" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="732" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="composite" type="233" />
+     <UML:AssociationEndRole visibility="public" type="227" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="816" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="212" />
+     <UML:AssociationEndRole visibility="public" type="262" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="1058" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="233" />
+     <UML:AssociationEndRole visibility="public" type="733" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="1059" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="226" />
+     <UML:AssociationEndRole visibility="public" type="733" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="1263" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="214" />
+     <UML:AssociationEndRole visibility="public" type="217" />
+    </UML:Association.connection>
+   </UML:Association>
+  </UML:Model>
+  <diagrams>
+   <diagram snapgrid="1" showattsig="1" fillcolor="#ffffc0" zoom="64" showgrid="1" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="5034" snapy="10" showatts="1" xmi.id="174" documentation="" type="402" showops="1" showpackage="0" name="class diagram" localid="30000" showstereotype="0" showscope="1" snapcsgrid="1" font="helvetica,12,-1,0,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="2844" >
+    <widgets>
+     <UML:ClassWidget usesdiagramfillcolour="0" width="430" showattsigs="601" usesdiagramusefillcolour="0" x="2420" linecolour="#ff0000" y="410" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="120" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="194" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="240" showattsigs="601" usesdiagramusefillcolour="0" x="3090" linecolour="#ff0000" y="410" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="100" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="195" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="1" width="230" showattsigs="601" usesdiagramusefillcolour="1" x="2490" linecolour="none" y="170" showopsigs="601" instancename="" usesdiagramlinecolour="1" fillcolour="none" height="40" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="189" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="helvetica,12,-1,0,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="710" showattsigs="601" usesdiagramusefillcolour="0" x="4320" linecolour="#ff0000" y="1010" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="140" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="200" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="580" showattsigs="601" usesdiagramusefillcolour="0" x="4390" linecolour="#ff0000" y="1220" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="60" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="199" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="640" showattsigs="601" usesdiagramusefillcolour="0" x="3660" linecolour="#ff0000" y="1010" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="180" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="225" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="420" showattsigs="601" usesdiagramusefillcolour="0" x="1540" linecolour="#ff0000" y="1010" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="270" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="220" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="430" showattsigs="601" usesdiagramusefillcolour="0" x="1030" linecolour="#ff0000" y="1010" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="580" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="214" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="480" showattsigs="601" usesdiagramusefillcolour="0" x="3160" linecolour="#ff0000" y="1010" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="520" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="233" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="1110" showattsigs="601" usesdiagramusefillcolour="0" x="2000" linecolour="#ff0000" y="1010" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="750" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="242" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="1310" showattsigs="601" usesdiagramusefillcolour="0" x="3500" linecolour="#ff0000" y="1770" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="480" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="226" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="770" showattsigs="601" usesdiagramusefillcolour="0" x="4230" linecolour="#ff0000" y="1530" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="140" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="227" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="780" showattsigs="601" usesdiagramusefillcolour="0" x="890" linecolour="#ff0000" y="1850" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="290" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="208" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="780" showattsigs="601" usesdiagramusefillcolour="0" x="1170" linecolour="#ff0000" y="2230" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="180" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="209" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="430" showattsigs="601" usesdiagramusefillcolour="0" x="2380" linecolour="#ff0000" y="2530" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="310" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="211" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="1100" showattsigs="601" usesdiagramusefillcolour="0" x="790" linecolour="#ff0000" y="2510" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="330" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="212" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="910" showattsigs="601" usesdiagramusefillcolour="0" x="2280" linecolour="#ff0000" y="1980" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="220" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="213" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="300" showattsigs="601" usesdiagramusefillcolour="0" x="880" linecolour="#ff0000" y="1700" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="100" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="215" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="380" showattsigs="601" usesdiagramusefillcolour="0" x="2590" linecolour="#ff0000" y="2260" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="140" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="217" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="250" showattsigs="601" usesdiagramusefillcolour="0" x="2830" linecolour="#ff0000" y="2530" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="120" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="218" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="610" showattsigs="601" usesdiagramusefillcolour="0" x="3120" linecolour="#ff0000" y="2480" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="270" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="733" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <UML:ClassWidget usesdiagramfillcolour="0" width="400" showattsigs="601" usesdiagramusefillcolour="0" x="1950" linecolour="#ff0000" y="2570" showopsigs="601" instancename="" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="220" usefillcolor="1" showattributes="1" isinstance="0" xmi.id="262" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+    </widgets>
+    <messages/>
+    <associations>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" widgetbid="189" widgetaid="194" xmi.id="600" >
+      <linepath>
+       <startpoint startx="2635" starty="410" />
+       <endpoint endx="2643" endy="210" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="2" totalcountb="6" indexb="5" widgetbid="195" widgetaid="200" xmi.id="602" >
+      <linepath>
+       <startpoint startx="4793" starty="1010" />
+       <endpoint endx="3290" endy="510" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="1" totalcountb="6" indexb="5" widgetbid="194" widgetaid="200" xmi.id="603" >
+      <linepath>
+       <startpoint startx="4556" starty="1010" />
+       <endpoint endx="2778" endy="530" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="199" widgetaid="200" xmi.id="605" >
+      <linepath>
+       <startpoint startx="4675" starty="1150" />
+       <endpoint endx="4680" endy="1220" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="2" totalcountb="6" indexb="4" widgetbid="195" widgetaid="225" xmi.id="615" >
+      <linepath>
+       <startpoint startx="4086" starty="1010" />
+       <endpoint endx="3250" endy="510" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="1" totalcountb="6" indexb="4" widgetbid="194" widgetaid="225" xmi.id="616" >
+      <linepath>
+       <startpoint startx="3873" starty="1010" />
+       <endpoint endx="2706" endy="530" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="1" totalcountb="6" indexb="1" widgetbid="194" widgetaid="220" xmi.id="625" >
+      <linepath>
+       <startpoint startx="1680" starty="1010" />
+       <endpoint endx="2491" endy="530" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="2" totalcountb="6" indexb="1" widgetbid="195" widgetaid="220" xmi.id="626" >
+      <linepath>
+       <startpoint startx="1820" starty="1010" />
+       <endpoint endx="3130" endy="510" />
+       <point x="1860" y="980" />
+       <point x="2660" y="690" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="1" totalcountb="6" indexb="3" widgetbid="194" widgetaid="233" xmi.id="645" >
+      <linepath>
+       <startpoint startx="3320" starty="1010" />
+       <endpoint endx="2635" endy="530" />
+       <point x="3060" y="840" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="2" totalcountb="6" indexb="3" widgetbid="195" widgetaid="233" xmi.id="646" >
+      <linepath>
+       <startpoint startx="3480" starty="1010" />
+       <endpoint endx="3210" endy="510" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="1" totalcountb="6" indexb="2" widgetbid="194" widgetaid="242" xmi.id="655" >
+      <linepath>
+       <startpoint startx="2370" starty="1010" />
+       <endpoint endx="2563" endy="530" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="2" totalcountb="6" indexb="2" widgetbid="195" widgetaid="242" xmi.id="656" >
+      <linepath>
+       <startpoint startx="2740" starty="1010" />
+       <endpoint endx="3170" endy="510" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" widgetbid="225" widgetaid="227" xmi.id="669" >
+      <linepath>
+       <startpoint startx="4615" starty="1530" />
+       <endpoint endx="4086" endy="1190" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" widgetbid="225" widgetaid="226" xmi.id="670" >
+      <linepath>
+       <startpoint startx="4155" starty="1770" />
+       <endpoint endx="3873" endy="1190" />
+       <point x="4120" y="1960" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" widgetbid="189" widgetaid="214" xmi.id="679" >
+      <linepath>
+       <startpoint startx="1245" starty="1010" />
+       <endpoint endx="2566" endy="210" />
+       <point x="1250" y="980" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="1" totalcountb="2" indexb="1" widgetbid="208" widgetaid="214" xmi.id="681" >
+      <linepath>
+       <startpoint startx="1173" starty="1590" />
+       <endpoint endx="1280" endy="1850" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" widgetbid="208" widgetaid="209" xmi.id="695" >
+      <linepath>
+       <startpoint startx="1560" starty="2230" />
+       <endpoint endx="1410" endy="2140" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" widgetbid="208" widgetaid="212" xmi.id="705" >
+      <linepath>
+       <startpoint startx="1340" starty="2510" />
+       <endpoint endx="1150" endy="2140" />
+       <point x="1150" y="2440" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" widgetbid="208" widgetaid="213" xmi.id="706" >
+      <linepath>
+       <startpoint startx="2280" starty="2090" />
+       <endpoint endx="1670" endy="1946" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="3" indexb="2" widgetbid="214" widgetaid="215" roleBdoc="" roleAdoc="" type="503" changeabilityA="900" changeabilityB="900" visibilityA="200" >
+      <linepath>
+       <startpoint startx="1030" starty="1700" />
+       <endpoint endx="1316" endy="1590" />
+       <point x="1140" y="1640" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="1" totalcountb="3" indexb="1" widgetbid="214" widgetaid="226" xmi.id="708" >
+      <linepath>
+       <startpoint startx="3500" starty="1930" />
+       <endpoint endx="1460" endy="1203" />
+       <point x="1940" y="1870" />
+      </linepath>
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="2710" linecolour="none" y="2010" instancename="" posttext="" usesdiagramlinecolour="1" role="703" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="708" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="3490" linecolour="none" y="2000" instancename="" posttext="" usesdiagramlinecolour="1" role="701" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="708" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="1420" linecolour="none" y="1200" instancename="" posttext="" usesdiagramlinecolour="1" role="702" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="708" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="3470" linecolour="none" y="1960" instancename="" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="708" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="1430" linecolour="none" y="1200" instancename="" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="708" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="2" totalcountb="3" indexb="1" widgetbid="211" widgetaid="208" xmi.id="715" >
+      <linepath>
+       <startpoint startx="1670" starty="2043" />
+       <endpoint endx="2523" endy="2530" />
+       <point x="1890" y="2080" />
+       <point x="2090" y="2370" />
+       <point x="2360" y="2460" />
+      </linepath>
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="2700" linecolour="none" y="2630" instancename="" posttext="" usesdiagramlinecolour="1" role="703" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="715" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="1650" linecolour="none" y="1990" instancename="" posttext="" usesdiagramlinecolour="1" role="701" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="715" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="2510" linecolour="none" y="2540" instancename="" posttext="" usesdiagramlinecolour="1" role="702" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="715" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="1660" linecolour="none" y="2020" instancename="" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="715" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="2490" linecolour="none" y="2510" instancename="" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="715" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="2" totalcountb="3" indexb="1" widgetbid="217" widgetaid="211" xmi.id="716" >
+      <linepath>
+       <startpoint startx="2666" starty="2530" />
+       <endpoint endx="2716" endy="2400" />
+      </linepath>
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="2480" linecolour="none" y="2650" instancename="" posttext="" usesdiagramlinecolour="1" role="703" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="716" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="2340" linecolour="none" y="2680" instancename="" posttext="" usesdiagramlinecolour="1" role="701" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="716" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="2720" linecolour="none" y="2370" instancename="" posttext="" usesdiagramlinecolour="1" role="702" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="716" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="2350" linecolour="none" y="2730" instancename="" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="716" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="2690" linecolour="none" y="2380" instancename="" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="716" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="3" indexb="2" widgetbid="217" widgetaid="218" roleBdoc="" roleAdoc="" type="503" changeabilityA="900" changeabilityB="900" visibilityA="200" >
+      <linepath>
+       <startpoint startx="2955" starty="2530" />
+       <endpoint endx="2843" endy="2400" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="233" widgetaid="242" xmi.id="721" >
+      <linepath>
+       <startpoint startx="3110" starty="1385" />
+       <endpoint endx="3160" endy="1270" />
+      </linepath>
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="3100" linecolour="none" y="1310" instancename="" posttext="" usesdiagramlinecolour="1" role="703" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="721" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="3030" linecolour="none" y="1370" instancename="" posttext="" usesdiagramlinecolour="1" role="701" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="721" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="3150" linecolour="none" y="1220" instancename="" posttext="" usesdiagramlinecolour="1" role="702" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="721" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="3030" linecolour="none" y="1330" instancename="" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="721" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="3130" linecolour="none" y="1260" instancename="" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="721" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="220" widgetaid="242" xmi.id="722" >
+      <linepath>
+       <startpoint startx="2000" starty="1385" />
+       <endpoint endx="1750" endy="1280" />
+       <point x="1810" y="1370" />
+      </linepath>
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="2010" linecolour="none" y="1450" instancename="" posttext="" usesdiagramlinecolour="1" role="703" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="722" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="1980" linecolour="none" y="1400" instancename="" posttext="" usesdiagramlinecolour="1" role="701" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="722" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="1550" linecolour="none" y="1350" instancename="" posttext="" usesdiagramlinecolour="1" role="702" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="722" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="1970" linecolour="none" y="1330" instancename="" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="722" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="1550" linecolour="none" y="1390" instancename="" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="722" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="2" totalcountb="3" indexb="2" widgetbid="226" widgetaid="233" xmi.id="731" >
+      <linepath>
+       <startpoint startx="3480" starty="1530" />
+       <endpoint endx="3500" endy="2090" />
+       <point x="3810" y="1940" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="227" widgetaid="233" xmi.id="732" >
+      <linepath>
+       <startpoint startx="3640" starty="1270" />
+       <endpoint endx="4230" endy="1600" />
+       <point x="4200" y="1570" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="262" widgetaid="212" xmi.id="816" >
+      <linepath>
+       <startpoint startx="1890" starty="2675" />
+       <endpoint endx="1950" endy="2680" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="1" totalcountb="3" indexb="1" widgetbid="733" widgetaid="233" xmi.id="1058" >
+      <linepath>
+       <startpoint startx="3320" starty="1530" />
+       <endpoint endx="3323" endy="2480" />
+      </linepath>
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="3360" linecolour="none" y="2030" instancename="" posttext="" usesdiagramlinecolour="1" role="703" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="1058" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="3300" linecolour="none" y="1500" instancename="" posttext="" usesdiagramlinecolour="1" role="701" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="1058" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="10" usesdiagramusefillcolour="1" x="3310" linecolour="none" y="2450" instancename="" posttext="" usesdiagramlinecolour="1" role="702" fillcolour="none" height="30" usefillcolor="1" pretext="" isinstance="0" xmi.id="1058" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="3310" linecolour="none" y="1500" instancename="" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1058" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <UML:FloatingTextWidget usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="3280" linecolour="none" y="2450" instancename="" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1058" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" widgetbid="733" widgetaid="226" xmi.id="1059" >
+      <linepath>
+       <startpoint startx="4155" starty="2250" />
+       <endpoint endx="3526" endy="2480" />
+      </linepath>
+     </UML:AssocWidget>
+     <UML:AssocWidget totalcounta="3" indexa="2" totalcountb="2" indexb="1" widgetbid="217" widgetaid="214" xmi.id="1263" >
+      <linepath>
+       <startpoint startx="1460" starty="1396" />
+       <endpoint endx="2590" endy="2330" />
+       <point x="1920" y="1990" />
+       <point x="2150" y="2320" />
+      </linepath>
+     </UML:AssocWidget>
+    </associations>
+   </diagram>
+  </diagrams>
+  <listview>
+   <listitem open="1" type="800" id="-1" label="Views" >
+    <listitem open="1" type="801" id="-1" label="Logical View" >
+     <listitem open="0" type="803" id="187" label="Lib Paket" />
+     <listitem open="1" type="803" id="192" label="Modul Paket" />
+     <listitem open="0" type="807" id="174" label="class diagram" />
+     <listitem open="0" type="818" id="188" label="Lib.connector" >
+      <listitem open="1" type="813" id="189" label="Publisher" />
+     </listitem>
+     <listitem open="1" type="818" id="186" label="Model.base" >
+      <listitem open="1" type="813" id="194" label="Modifiable" >
+       <listitem open="0" type="815" id="889" label="UnsetModified" />
+       <listitem open="0" type="815" id="892" label="WasModified" />
+       <listitem open="0" type="815" id="891" label="__init__" />
+       <listitem open="0" type="815" id="890" label="changed" />
+      </listitem>
+      <listitem open="1" type="813" id="195" label="TitledObject" >
+       <listitem open="0" type="815" id="921" label="SetTitle" />
+       <listitem open="0" type="815" id="920" label="Title" />
+       <listitem open="0" type="815" id="919" label="__init__" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="818" id="280" label="Model.classgen" >
+      <listitem open="1" type="813" id="281" label="CustomRamp" />
+      <listitem open="1" type="813" id="282" label="FixedRamp" />
+      <listitem open="1" type="813" id="283" label="HotToColdRamp" />
+      <listitem open="1" type="813" id="284" label="MonochromaticRamp" />
+     </listitem>
+     <listitem open="1" type="818" id="207" label="Model.classification" >
+      <listitem open="1" type="813" id="208" label="ClassGroup" >
+       <listitem open="0" type="815" id="1185" label="GetDisplayText" />
+       <listitem open="0" type="815" id="1186" label="GetLabel" />
+       <listitem open="0" type="815" id="1187" label="GetProperties" />
+       <listitem open="0" type="815" id="1189" label="IsVisible" />
+       <listitem open="0" type="815" id="1190" label="Matches" />
+       <listitem open="0" type="815" id="1193" label="SetLabel" />
+       <listitem open="0" type="815" id="1194" label="SetProperties" />
+       <listitem open="0" type="815" id="1195" label="SetVisible" />
+       <listitem open="0" type="815" id="1184" label="__eq__" />
+       <listitem open="0" type="815" id="1188" label="__init__" />
+       <listitem open="0" type="815" id="1191" label="__ne__" />
+       <listitem open="0" type="815" id="1192" label="__repr__" />
+      </listitem>
+      <listitem open="1" type="813" id="209" label="ClassGroupDefault" >
+       <listitem open="0" type="815" id="1199" label="GetDisplayText" />
+       <listitem open="0" type="815" id="1201" label="Matches" />
+       <listitem open="0" type="815" id="1196" label="__copy__" />
+       <listitem open="0" type="815" id="1197" label="__deepcopy__" />
+       <listitem open="0" type="815" id="1198" label="__eq__" />
+       <listitem open="0" type="815" id="1200" label="__init__" />
+       <listitem open="0" type="815" id="1202" label="__repr__" />
+      </listitem>
+      <listitem open="1" type="813" id="210" label="ClassGroupMap" />
+      <listitem open="1" type="813" id="211" label="ClassGroupProperties" >
+       <listitem open="0" type="815" id="1244" label="GetFill" />
+       <listitem open="0" type="815" id="1245" label="GetLineColor" />
+       <listitem open="0" type="815" id="1246" label="GetLineWidth" />
+       <listitem open="0" type="815" id="1250" label="SetFill" />
+       <listitem open="0" type="815" id="1251" label="SetLineColor" />
+       <listitem open="0" type="815" id="1252" label="SetLineWidth" />
+       <listitem open="0" type="815" id="1253" label="SetProperties" />
+       <listitem open="0" type="815" id="1241" label="__copy__" />
+       <listitem open="0" type="815" id="1242" label="__deepcopy__" />
+       <listitem open="0" type="815" id="1243" label="__eq__" />
+       <listitem open="0" type="815" id="1247" label="__init__" />
+       <listitem open="0" type="815" id="1248" label="__ne__" />
+       <listitem open="0" type="815" id="1249" label="__repr__" />
+      </listitem>
+      <listitem open="1" type="813" id="212" label="ClassGroupRange" >
+       <listitem open="0" type="815" id="1212" label="GetDisplayText" />
+       <listitem open="0" type="815" id="1213" label="GetMax" />
+       <listitem open="0" type="815" id="1214" label="GetMin" />
+       <listitem open="0" type="815" id="1215" label="GetRange" />
+       <listitem open="0" type="815" id="1216" label="GetRangeTuple" />
+       <listitem open="0" type="815" id="1218" label="Matches" />
+       <listitem open="0" type="815" id="1220" label="SetMax" />
+       <listitem open="0" type="815" id="1221" label="SetMin" />
+       <listitem open="0" type="815" id="1222" label="SetRange" />
+       <listitem open="0" type="815" id="1209" label="__copy__" />
+       <listitem open="0" type="815" id="1210" label="__deepcopy__" />
+       <listitem open="0" type="815" id="1211" label="__eq__" />
+       <listitem open="0" type="815" id="1217" label="__init__" />
+       <listitem open="0" type="815" id="1219" label="__repr__" />
+      </listitem>
+      <listitem open="1" type="813" id="213" label="ClassGroupSingleton" >
+       <listitem open="0" type="815" id="1235" label="GetDisplayText" />
+       <listitem open="0" type="815" id="1236" label="GetValue" />
+       <listitem open="0" type="815" id="1238" label="Matches" />
+       <listitem open="0" type="815" id="1240" label="SetValue" />
+       <listitem open="0" type="815" id="1232" label="__copy__" />
+       <listitem open="0" type="815" id="1233" label="__deepcopy__" />
+       <listitem open="0" type="815" id="1234" label="__eq__" />
+       <listitem open="0" type="815" id="1237" label="__init__" />
+       <listitem open="0" type="815" id="1239" label="__repr__" />
+      </listitem>
+      <listitem open="1" type="813" id="215" label="ClassIterator" >
+       <listitem open="0" type="815" id="1181" label="__init__" />
+       <listitem open="0" type="815" id="1182" label="__iter__" />
+       <listitem open="0" type="815" id="1183" label="next" />
+      </listitem>
+      <listitem open="1" type="813" id="214" label="Classification" >
+       <listitem open="0" type="815" id="1154" label="AppendGroup" />
+       <listitem open="0" type="815" id="1160" label="FindGroup" />
+       <listitem open="0" type="815" id="1162" label="GetDefaultFill" />
+       <listitem open="0" type="815" id="1163" label="GetDefaultGroup" />
+       <listitem open="0" type="815" id="1164" label="GetDefaultLineColor" />
+       <listitem open="0" type="815" id="1165" label="GetDefaultLineWidth" />
+       <listitem open="0" type="815" id="1166" label="GetGroup" />
+       <listitem open="0" type="815" id="1167" label="GetNumGroups" />
+       <listitem open="0" type="815" id="1168" label="GetProperties" />
+       <listitem open="0" type="815" id="1170" label="InsertGroup" />
+       <listitem open="0" type="815" id="1172" label="RemoveGroup" />
+       <listitem open="0" type="815" id="1173" label="ReplaceGroup" />
+       <listitem open="0" type="815" id="1175" label="SetDefaultFill" />
+       <listitem open="0" type="815" id="1177" label="SetDefaultGroup" />
+       <listitem open="0" type="815" id="1178" label="SetDefaultLineColor" />
+       <listitem open="0" type="815" id="1179" label="SetDefaultLineWidth" />
+       <listitem open="0" type="815" id="1180" label="TreeInfo" />
+       <listitem open="0" type="815" id="1174" label="__SendNotification" />
+       <listitem open="0" type="815" id="1159" label="__deepcopy__" />
+       <listitem open="0" type="815" id="1161" label="__getattr__" />
+       <listitem open="0" type="815" id="1169" label="__init__" />
+       <listitem open="0" type="815" id="1171" label="__iter__" />
+       <listitem open="0" type="815" id="1157" label="_clear_compiled_classification" />
+       <listitem open="0" type="815" id="1158" label="_compile_classification" />
+       <listitem open="0" type="815" id="1155" label="build_color_item" />
+       <listitem open="0" type="815" id="1156" label="build_item" />
+      </listitem>
+     </listitem>
+     <listitem open="1" type="818" id="216" label="Model.color" >
+      <listitem open="1" type="813" id="217" label="Color" >
+       <listitem open="0" type="815" id="1258" label="__eq__" />
+       <listitem open="0" type="815" id="1260" label="__init__" />
+       <listitem open="0" type="815" id="1261" label="__ne__" />
+       <listitem open="0" type="815" id="1262" label="__repr__" />
+       <listitem open="0" type="815" id="1259" label="hex" />
+      </listitem>
+      <listitem open="1" type="813" id="218" label="_Transparent" >
+       <listitem open="0" type="815" id="1254" label="__eq__" />
+       <listitem open="0" type="815" id="1256" label="__ne__" />
+       <listitem open="0" type="815" id="1257" label="__repr__" />
+       <listitem open="0" type="815" id="1255" label="hex" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="818" id="264" label="Model.data" >
+      <listitem open="1" type="813" id="265" label="DerivedShapeStore" />
+      <listitem open="1" type="813" id="268" label="ShapeTable" />
+      <listitem open="1" type="813" id="266" label="ShapefileShape" />
+      <listitem open="1" type="813" id="267" label="ShapefileStore" />
+     </listitem>
+     <listitem open="1" type="818" id="219" label="Model.extension" >
+      <listitem open="1" type="813" id="220" label="Extension" >
+       <listitem open="0" type="815" id="1143" label="AddObject" />
+       <listitem open="0" type="815" id="1144" label="Destroy" />
+       <listitem open="0" type="815" id="1145" label="FindObject" />
+       <listitem open="0" type="815" id="1147" label="HasObjects" />
+       <listitem open="0" type="815" id="1149" label="Objects" />
+       <listitem open="0" type="815" id="1150" label="RemoveObject" />
+       <listitem open="0" type="815" id="1151" label="TreeInfo" />
+       <listitem open="0" type="815" id="1152" label="UnsetModified" />
+       <listitem open="0" type="815" id="1153" label="WasModified" />
+       <listitem open="0" type="815" id="1148" label="__init__" />
+       <listitem open="0" type="815" id="1146" label="forward" />
+      </listitem>
+     </listitem>
+     <listitem open="1" type="818" id="198" label="Model.label" >
+      <listitem open="1" type="813" id="199" label="Label" >
+       <listitem open="0" type="815" id="928" label="__init__" />
+      </listitem>
+      <listitem open="1" type="813" id="200" label="LabelLayer" >
+       <listitem open="0" type="815" id="923" label="AddLabel" />
+       <listitem open="0" type="815" id="924" label="ClearLabels" />
+       <listitem open="0" type="815" id="926" label="Labels" />
+       <listitem open="0" type="815" id="927" label="RemoveLabels" />
+       <listitem open="0" type="815" id="925" label="__init__" />
+      </listitem>
+     </listitem>
+     <listitem open="1" type="818" id="224" label="Model.layer" >
+      <listitem open="1" type="813" id="225" label="BaseLayer" >
+       <listitem open="0" type="815" id="931" label="GetProjection" />
+       <listitem open="0" type="815" id="932" label="HasClassification" />
+       <listitem open="0" type="815" id="933" label="HasShapes" />
+       <listitem open="0" type="815" id="935" label="SetProjection" />
+       <listitem open="0" type="815" id="936" label="SetVisible" />
+       <listitem open="0" type="815" id="937" label="Visible" />
+       <listitem open="0" type="815" id="934" label="__init__" />
+      </listitem>
+      <listitem open="1" type="813" id="226" label="Layer" >
+       <listitem open="0" type="815" id="943" label="BoundingBox" />
+       <listitem open="0" type="815" id="945" label="ClipBoundingBox" />
+       <listitem open="0" type="815" id="946" label="Destroy" />
+       <listitem open="0" type="815" id="948" label="GetClassification" />
+       <listitem open="0" type="815" id="947" label="GetClassificationColumn" />
+       <listitem open="0" type="815" id="949" label="GetFieldType" />
+       <listitem open="0" type="815" id="950" label="HasClassification" />
+       <listitem open="0" type="815" id="951" label="HasShapes" />
+       <listitem open="0" type="815" id="953" label="LatLongBoundingBox" />
+       <listitem open="0" type="815" id="954" label="NumShapes" />
+       <listitem open="0" type="815" id="956" label="SetClassification" />
+       <listitem open="0" type="815" id="955" label="SetClassificationColumn" />
+       <listitem open="0" type="815" id="957" label="SetShapeStore" />
+       <listitem open="0" type="815" id="962" label="ShapeStore" />
+       <listitem open="0" type="815" id="963" label="ShapeType" />
+       <listitem open="0" type="815" id="959" label="Shapes" />
+       <listitem open="0" type="815" id="958" label="ShapesBoundingBox" />
+       <listitem open="0" type="815" id="960" label="ShapesInRegion" />
+       <listitem open="0" type="815" id="964" label="TreeInfo" />
+       <listitem open="0" type="815" id="952" label="__init__" />
+       <listitem open="0" type="815" id="944" label="_classification_changed" />
+      </listitem>
+      <listitem open="1" type="813" id="227" label="RasterLayer" >
+       <listitem open="0" type="815" id="938" label="BoundingBox" />
+       <listitem open="0" type="815" id="939" label="GetImageFilename" />
+       <listitem open="0" type="815" id="941" label="LatLongBox" />
+       <listitem open="0" type="815" id="942" label="TreeInfo" />
+       <listitem open="0" type="815" id="940" label="__init__" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="818" id="269" label="Model.load" >
+      <listitem open="1" type="813" id="270" label="AttrDesc" />
+      <listitem open="1" type="813" id="271" label="LoadCancelled" />
+      <listitem open="1" type="813" id="272" label="LoadError" />
+      <listitem open="1" type="813" id="273" label="SessionLoader" />
+     </listitem>
+     <listitem open="1" type="818" id="232" label="Model.map" >
+      <listitem open="1" type="813" id="233" label="Map" >
+       <listitem open="0" type="815" id="1060" label="AddLayer" />
+       <listitem open="0" type="815" id="1061" label="BoundingBox" />
+       <listitem open="0" type="815" id="1062" label="CanRemoveLayer" />
+       <listitem open="0" type="815" id="1063" label="ClearLayers" />
+       <listitem open="0" type="815" id="1064" label="Destroy" />
+       <listitem open="0" type="815" id="1066" label="GetProjection" />
+       <listitem open="0" type="815" id="1067" label="HasLayers" />
+       <listitem open="0" type="815" id="1069" label="LabelLayer" />
+       <listitem open="0" type="815" id="1070" label="Layers" />
+       <listitem open="0" type="815" id="1071" label="LowerLayer" />
+       <listitem open="0" type="815" id="1072" label="MoveLayerToBottom" />
+       <listitem open="0" type="815" id="1073" label="MoveLayerToTop" />
+       <listitem open="0" type="815" id="1074" label="ProjectedBoundingBox" />
+       <listitem open="0" type="815" id="1075" label="RaiseLayer" />
+       <listitem open="0" type="815" id="1076" label="RemoveLayer" />
+       <listitem open="0" type="815" id="1077" label="SetProjection" />
+       <listitem open="0" type="815" id="1079" label="TreeInfo" />
+       <listitem open="0" type="815" id="1080" label="UnsetModified" />
+       <listitem open="0" type="815" id="1082" label="WasModified" />
+       <listitem open="0" type="815" id="1068" label="__init__" />
+       <listitem open="0" type="815" id="1065" label="forward" />
+       <listitem open="0" type="815" id="1078" label="subscribe_layer_channels" />
+       <listitem open="0" type="815" id="1081" label="unsubscribe_layer_channels" />
+      </listitem>
+     </listitem>
+     <listitem open="1" type="818" id="196" label="Model.messages" />
+     <listitem open="0" type="818" id="285" label="Model.postgisdb" >
+      <listitem open="1" type="813" id="286" label="ConnectionError" />
+      <listitem open="1" type="813" id="287" label="PostGISColumn" />
+      <listitem open="1" type="813" id="288" label="PostGISConnection" />
+      <listitem open="1" type="813" id="289" label="PostGISShape" />
+      <listitem open="1" type="813" id="825" label="PostGISShapeStore" />
+      <listitem open="1" type="813" id="291" label="PostGISTable" />
+     </listitem>
+     <listitem open="1" type="818" id="236" label="Model.proj" >
+      <listitem open="1" type="813" id="237" label="BaseProjection" />
+      <listitem open="1" type="813" id="238" label="ProjFile" />
+      <listitem open="1" type="813" id="733" label="Projection" >
+       <listitem open="0" type="815" id="991" label="EPSGCode" />
+       <listitem open="0" type="815" id="992" label="ForwardBBox" />
+       <listitem open="0" type="815" id="993" label="GetAllParameters" />
+       <listitem open="0" type="815" id="994" label="GetName" />
+       <listitem open="0" type="815" id="995" label="GetParameter" />
+       <listitem open="0" type="815" id="996" label="GetProjectedUnits" />
+       <listitem open="0" type="815" id="998" label="InverseBBox" />
+       <listitem open="0" type="815" id="999" label="Label" />
+       <listitem open="0" type="815" id="997" label="__init__" />
+       <listitem open="0" type="815" id="1000" label="__repr__" />
+       <listitem open="0" type="815" id="1001" label="_transform_bbox" />
+      </listitem>
+     </listitem>
+     <listitem open="1" type="818" id="261" label="Model.range" >
+      <listitem open="1" type="813" id="262" label="Range" >
+       <listitem open="0" type="815" id="1226" label="GetRange" />
+       <listitem open="0" type="815" id="1229" label="_SetRange" />
+       <listitem open="0" type="815" id="1223" label="__contains__" />
+       <listitem open="0" type="815" id="1224" label="__eq__" />
+       <listitem open="0" type="815" id="1227" label="__init__" />
+       <listitem open="0" type="815" id="1228" label="__ne__" />
+       <listitem open="0" type="815" id="1231" label="__str__" />
+       <listitem open="0" type="815" id="1225" label="_float2string" />
+       <listitem open="0" type="815" id="1230" label="string" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="818" id="292" label="Model.resource" >
+      <listitem open="1" type="813" id="293" label="ProjFileReader" />
+      <listitem open="1" type="813" id="294" label="ProjFileSaver" />
+     </listitem>
+     <listitem open="0" type="818" id="295" label="Model.save" >
+      <listitem open="1" type="813" id="296" label="SessionSaver" />
+     </listitem>
+     <listitem open="1" type="818" id="297" label="Model.scalebar" />
+     <listitem open="1" type="818" id="239" label="Model.session" >
+      <listitem open="1" type="813" id="240" label="AutoRemoveDir" />
+      <listitem open="1" type="813" id="241" label="AutoRemoveFile" />
+      <listitem open="1" type="813" id="242" label="Session" >
+       <listitem open="0" type="815" id="1083" label="AddDBConnection" />
+       <listitem open="0" type="815" id="1084" label="AddExtension" />
+       <listitem open="0" type="815" id="1085" label="AddMap" />
+       <listitem open="0" type="815" id="1086" label="AddShapeStore" />
+       <listitem open="0" type="815" id="1088" label="AddTable" />
+       <listitem open="0" type="815" id="1089" label="CanRemoveDBConnection" />
+       <listitem open="0" type="815" id="1093" label="DBConnections" />
+       <listitem open="0" type="815" id="1092" label="DataContainers" />
+       <listitem open="0" type="815" id="1094" label="Destroy" />
+       <listitem open="0" type="815" id="1095" label="Extensions" />
+       <listitem open="0" type="815" id="1097" label="HasDBConnections" />
+       <listitem open="0" type="815" id="1098" label="HasExtensions" />
+       <listitem open="0" type="815" id="1099" label="HasMaps" />
+       <listitem open="0" type="815" id="1101" label="Maps" />
+       <listitem open="0" type="815" id="1102" label="OpenDBShapeStore" />
+       <listitem open="0" type="815" id="1103" label="OpenShapefile" />
+       <listitem open="0" type="815" id="1104" label="OpenTableFile" />
+       <listitem open="0" type="815" id="1105" label="RemoveDBConnection" />
+       <listitem open="0" type="815" id="1106" label="RemoveMap" />
+       <listitem open="0" type="815" id="1107" label="RemoveTable" />
+       <listitem open="0" type="815" id="1108" label="SetFilename" />
+       <listitem open="0" type="815" id="1109" label="ShapeStores" />
+       <listitem open="0" type="815" id="1110" label="Tables" />
+       <listitem open="0" type="815" id="1112" label="TransientDB" />
+       <listitem open="0" type="815" id="1113" label="TreeInfo" />
+       <listitem open="0" type="815" id="1114" label="UnreferencedTables" />
+       <listitem open="0" type="815" id="1115" label="UnsetModified" />
+       <listitem open="0" type="815" id="1116" label="WasModified" />
+       <listitem open="0" type="815" id="1100" label="__init__" />
+       <listitem open="0" type="815" id="1087" label="_add_shapestore" />
+       <listitem open="0" type="815" id="1091" label="_clean_weak_store_refs" />
+       <listitem open="0" type="815" id="1090" label="changed" />
+       <listitem open="0" type="815" id="1096" label="forward" />
+       <listitem open="0" type="815" id="1111" label="temp_directory" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="818" id="298" label="Model.table" >
+      <listitem open="1" type="813" id="299" label="DBFColumn" />
+      <listitem open="1" type="813" id="300" label="DBFTable" />
+      <listitem open="1" type="813" id="301" label="MemoryColumn" />
+      <listitem open="1" type="813" id="302" label="MemoryTable" />
+     </listitem>
+     <listitem open="0" type="818" id="303" label="Model.transientdb" >
+      <listitem open="1" type="813" id="304" label="AutoTransientTable" />
+      <listitem open="1" type="813" id="305" label="ColiumnReference" />
+      <listitem open="1" type="813" id="306" label="TransientDatabase" />
+      <listitem open="1" type="813" id="307" label="TransientJoinedTable" />
+      <listitem open="1" type="813" id="309" label="TransientTable" />
+      <listitem open="1" type="813" id="308" label="TransientTableBase" />
+     </listitem>
+     <listitem open="1" type="818" id="310" label="Model.wellknowntext" />
+     <listitem open="0" type="818" id="311" label="Model.xmlreader" >
+      <listitem open="1" type="813" id="313" label="XMLReader" />
+     </listitem>
+     <listitem open="0" type="818" id="312" label="Model.xmlwriter" >
+      <listitem open="1" type="813" id="314" label="XMLWriter" />
+     </listitem>
+     <listitem open="0" type="830" id="-1" label="Datatypes" >
+      <listitem open="1" type="829" id="177" label="bool" />
+      <listitem open="1" type="829" id="176" label="char" />
+      <listitem open="1" type="829" id="179" label="double" />
+      <listitem open="1" type="829" id="178" label="float" />
+      <listitem open="1" type="829" id="175" label="int" />
+      <listitem open="1" type="829" id="180" label="long" />
+      <listitem open="1" type="829" id="181" label="short" />
+     </listitem>
+    </listitem>
+    <listitem open="1" type="802" id="-1" label="Use Case View" />
+    <listitem open="1" type="821" id="-1" label="Component View" />
+    <listitem open="1" type="827" id="-1" label="Deployment View" />
+   </listitem>
+  </listview>
+  <codegeneration/>
+ </XMI.content>
+</XMI>

Added: packages/thuban/branches/upstream/current/Doc/ThubanModel.xmi
===================================================================
--- packages/thuban/branches/upstream/current/Doc/ThubanModel.xmi	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/ThubanModel.xmi	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1515 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XMI xmlns:UML="org.omg/standards/UML" verified="false" timestamp="" xmi.version="1.2" >
+ <XMI.header>
+  <XMI.documentation>
+   <XMI.exporter>umbrello uml modeller http://uml.sf.net</XMI.exporter>
+   <XMI.exporterVersion>1.2.90</XMI.exporterVersion>
+   <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
+  </XMI.documentation>
+  <XMI.model xmi.name="ThubanModel" href="./ThubanModel.xmi" />
+  <XMI.metamodel xmi.name="UML" href="UML.xml" xmi.version="1.3" />
+ </XMI.header>
+ <XMI.content>
+  <UML:Model>
+   <UML:Stereotype visibility="public" xmi.id="1358" name="datatype" />
+   <UML:Stereotype visibility="public" xmi.id="1365" name="class" />
+   <UML:Stereotype visibility="public" xmi.id="1366" name="Lib" />
+   <UML:DataType stereotype="1358" visibility="public" xmi.id="175" name="int" />
+   <UML:DataType stereotype="1358" visibility="public" xmi.id="176" name="char" />
+   <UML:DataType stereotype="1358" visibility="public" xmi.id="177" name="bool" />
+   <UML:DataType stereotype="1358" visibility="public" xmi.id="178" name="float" />
+   <UML:DataType stereotype="1358" visibility="public" xmi.id="179" name="double" />
+   <UML:DataType stereotype="1358" visibility="public" xmi.id="180" name="long" />
+   <UML:DataType stereotype="1358" visibility="public" xmi.id="181" name="short" />
+   <UML:Package visibility="public" xmi.id="186" name="Model.base" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="194" name="Modifiable" >
+     <UML:Operation visibility="public" xmi.id="889" type="void" name="UnsetModified" />
+     <UML:Operation visibility="public" xmi.id="890" type="void" name="changed" >
+      <UML:Parameter visibility="public" xmi.id="1" value="None" type="string" name="channel" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="int" name="*.args" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="891" type="void" name="__init__" />
+     <UML:Operation visibility="public" xmi.id="892" type="bool" name="WasModified" />
+    </UML:Class>
+    <UML:Class stereotype="1365" visibility="public" xmi.id="195" name="TitledObject" >
+     <UML:Operation visibility="public" xmi.id="919" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="920" type="string" name="Title" />
+     <UML:Operation visibility="public" xmi.id="921" type="void" name="SetTitle" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+    </UML:Class>
+   </UML:Package>
+   <UML:Package stereotype="1366" visibility="public" xmi.id="188" name="Lib.connector" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="189" name="Publisher" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="196" name="Model.messages" />
+   <UML:Package visibility="public" xmi.id="198" name="Model.label" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="199" name="Label" >
+     <UML:Operation visibility="public" xmi.id="928" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="x" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="int" name="y" />
+      <UML:Parameter visibility="public" xmi.id="3" value="" type="string" name="text" />
+      <UML:Parameter visibility="public" xmi.id="4" value="" type="string" name="halign" />
+      <UML:Parameter visibility="public" xmi.id="5" value="" type="string" name="valign" />
+     </UML:Operation>
+    </UML:Class>
+    <UML:Class stereotype="1365" visibility="public" xmi.id="200" name="LabelLayer" >
+     <UML:Operation visibility="public" xmi.id="923" type="void" name="AddLabel" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="x" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="int" name="y" />
+      <UML:Parameter visibility="public" xmi.id="3" value="" type="string" name="text" />
+      <UML:Parameter visibility="public" xmi.id="4" value="left" type="string" name="halign" />
+      <UML:Parameter visibility="public" xmi.id="5" value="center" type="string" name="valign" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="924" type="void" name="ClearLabels" />
+     <UML:Operation visibility="public" xmi.id="925" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="926" type="void" name="Labels" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Label" name="labels" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="927" type="void" name="RemoveLabels" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+     </UML:Operation>
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="207" name="Model.classification" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="208" name="ClassGroup" >
+     <UML:Operation visibility="public" xmi.id="1184" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1185" type="string" name="GetDisplayText" />
+     <UML:Operation visibility="public" xmi.id="1186" type="Label" name="GetLabel" />
+     <UML:Operation visibility="public" xmi.id="1187" type="ClassGroupProperties" name="GetProperties" />
+     <UML:Operation visibility="public" xmi.id="1188" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value=" " type="string" name="label" />
+      <UML:Parameter visibility="public" xmi.id="2" value="None" type="ClassGroupProperties" name="props" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1189" type="bool" name="IsVisible" />
+     <UML:Operation visibility="public" xmi.id="1190" type="bool" name="Matches" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="float" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1191" type="bool" name="__ne__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1192" type="string" name="__repr__" />
+     <UML:Operation visibility="public" xmi.id="1193" type="void" name="SetLabel" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="label" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1194" type="void" name="SetProperties" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroupProperties" name="prop" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1195" type="void" name="SetVisible" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="bool" name="visible" />
+     </UML:Operation>
+    </UML:Class>
+    <UML:Class stereotype="1365" visibility="public" xmi.id="209" name="ClassGroupDefault" >
+     <UML:Operation visibility="public" xmi.id="1196" type="ClassGroupDefault" name="__copy__" />
+     <UML:Operation visibility="public" xmi.id="1197" type="ClassGroupDefault" name="__deepcopy__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="memo" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1198" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1199" type="string" name="GetDisplayText" />
+     <UML:Operation visibility="public" xmi.id="1200" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="None" type="ClassGroupProperties" name="props" />
+      <UML:Parameter visibility="public" xmi.id="2" value=" " type="string" name="label" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1201" type="bool" name="Matches" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="float" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1202" type="string" name="__repr__" />
+    </UML:Class>
+    <UML:Class stereotype="1365" visibility="public" xmi.id="210" name="ClassGroupMap" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="211" name="ClassGroupProperties" >
+     <UML:Operation visibility="public" xmi.id="1241" type="ClassGroupProperties" name="__copy__" />
+     <UML:Operation visibility="public" xmi.id="1242" type="ClassGroupProperties" name="__deepcopy__" />
+     <UML:Operation visibility="public" xmi.id="1243" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroupProperties" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1244" type="Color" name="GetFill" />
+     <UML:Operation visibility="public" xmi.id="1245" type="Color" name="GetLineColor" />
+     <UML:Operation visibility="public" xmi.id="1246" type="int" name="GetLineWidth" />
+     <UML:Operation visibility="public" xmi.id="1247" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="None" type="ClassGroupProperties" name="props" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1248" type="bool" name="__ne__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroupProperties" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1249" type="string" name="__repr__" />
+     <UML:Operation visibility="public" xmi.id="1250" type="void" name="SetFill" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="fill" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1251" type="void" name="SetLineColor" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="color" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1252" type="void" name="SetLineWidth" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="lineWidth" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1253" type="void" name="SetProperties" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroupProperties" name="props" />
+     </UML:Operation>
+    </UML:Class>
+    <UML:Class stereotype="1365" visibility="public" xmi.id="212" name="ClassGroupRange" >
+     <UML:Operation visibility="public" xmi.id="1209" type="ClassGroupRange" name="__copy__" />
+     <UML:Operation visibility="public" xmi.id="1210" type="ClassGroupRange" name="__deepcopy__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="mono" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1211" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClasGroup" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1212" type="string" name="GetDisplayText" />
+     <UML:Operation visibility="public" xmi.id="1213" type="int" name="GetMax" />
+     <UML:Operation visibility="public" xmi.id="1214" type="int" name="GetMin" />
+     <UML:Operation visibility="public" xmi.id="1215" type="string" name="GetRange" />
+     <UML:Operation visibility="public" xmi.id="1216" type="string" name="GetRangeTuple" />
+     <UML:Operation visibility="public" xmi.id="1217" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="(0, 1)" type="int2 or ClassGroupRange" name="_range" />
+      <UML:Parameter visibility="public" xmi.id="2" value="None" type="ClassGroupProperties" name="props" />
+      <UML:Parameter visibility="public" xmi.id="3" value=" " type="string" name="label" />
+      <UML:Parameter visibility="public" xmi.id="4" value="None" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1218" type="bool" name="Matches" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1219" type="string" name="__repr__" />
+     <UML:Operation visibility="public" xmi.id="1220" type="void" name="SetMax" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="max" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1221" type="void" name="SetMin" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="min" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1222" type="void" name="SetRange" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int2 or Range" name="_range" />
+     </UML:Operation>
+    </UML:Class>
+    <UML:Class stereotype="1365" visibility="public" xmi.id="213" name="ClassGroupSingleton" >
+     <UML:Operation visibility="public" xmi.id="1232" type="ClassGroupSingleton" name="__copy__" />
+     <UML:Operation visibility="public" xmi.id="1233" type="ClassGroupSingleton" name="__deepcopy__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="mono" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1234" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1235" type="string" name="GetDisplayText" />
+     <UML:Operation visibility="public" xmi.id="1236" type="float" name="GetValue" />
+     <UML:Operation visibility="public" xmi.id="1237" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="0" type="float" name="value" />
+      <UML:Parameter visibility="public" xmi.id="2" value="None" type="ClassGroupProperties" name="props" />
+      <UML:Parameter visibility="public" xmi.id="3" value=" " type="string" name="label" />
+      <UML:Parameter visibility="public" xmi.id="4" value="None" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1238" type="bool" name="Matches" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="float" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1239" type="string" name="__repr__" />
+     <UML:Operation visibility="public" xmi.id="1240" type="void" name="SetValue" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="float" name="value" />
+     </UML:Operation>
+    </UML:Class>
+    <UML:Class stereotype="1365" visibility="public" xmi.id="214" name="Classification" >
+     <UML:Operation visibility="public" xmi.id="1154" type="void" name="AppendGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="item" />
+     </UML:Operation>
+     <UML:Operation visibility="private" xmi.id="1155" type="string" name="build_color_item" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="color" />
+     </UML:Operation>
+     <UML:Operation visibility="private" xmi.id="1156" type="string" name="build_item" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="string" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1157" type="void" name="_clear_compiled_classification" />
+     <UML:Operation visibility="public" xmi.id="1158" type="void" name="_compile_classification" />
+     <UML:Operation visibility="public" xmi.id="1159" type="Classification" name="__deepcopy__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="memo" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1160" type="ClassGroup" name="FindGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1161" type="void" name="__getattr__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="attr" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1162" type="Color" name="GetDefaultFill" />
+     <UML:Operation visibility="public" xmi.id="1163" type="ClassGroupDefault" name="GetDefaultGroup" />
+     <UML:Operation visibility="public" xmi.id="1164" type="Color" name="GetDefaultLineColor" />
+     <UML:Operation visibility="public" xmi.id="1165" type="int" name="GetDefaultLineWidth" />
+     <UML:Operation visibility="public" xmi.id="1166" type="ClassGroup" name="GetGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1167" type="int" name="GetNumGroups" />
+     <UML:Operation visibility="public" xmi.id="1168" type="ClassGroupProperties" name="GetProperties" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1169" type="void" name="__init__" />
+     <UML:Operation visibility="public" xmi.id="1170" type="void" name="InsertGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1171" type="ClassIterator" name="__iter__" />
+     <UML:Operation visibility="public" xmi.id="1172" type="void" name="RemoveGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1173" type="void" name="ReplaceGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1174" type="void" name="__SendNotification" />
+     <UML:Operation visibility="public" xmi.id="1175" type="void" name="SetDefaultFill" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="fill" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1177" type="void" name="SetDefaultGroup" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup" name="group" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1178" type="void" name="SetDefaultLineColor" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="color" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1179" type="void" name="SetDefaultLineWidth" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="lineWidth" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1180" type="string[]" name="TreeInfo" />
+    </UML:Class>
+    <UML:Class stereotype="1365" visibility="public" xmi.id="215" name="ClassIterator" >
+     <UML:Operation visibility="public" xmi.id="1181" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ClassGroup[]" name="data" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1182" type="ClassIterator" name="__iter__" />
+     <UML:Operation visibility="public" xmi.id="1183" type="ClassGroup" name="next" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="216" name="Model.color" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="217" name="Color" >
+     <UML:Operation visibility="public" xmi.id="1258" type="void" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1259" type="string" name="hex" />
+     <UML:Operation visibility="public" xmi.id="1260" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="red" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="int" name="green" />
+      <UML:Parameter visibility="public" xmi.id="3" value="" type="int" name="blue" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1261" type="bool" name="__ne__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Color" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1262" type="string" name="__repr__" />
+    </UML:Class>
+    <UML:Class stereotype="1365" comment="An object which represents no color." visibility="private" xmi.id="218" name="_Transparent" >
+     <UML:Operation visibility="public" xmi.id="1254" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Object" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1255" type="string" name="hex" />
+     <UML:Operation visibility="public" xmi.id="1256" type="bool" name="__ne__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Object" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1257" type="string" name="__repr__" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="219" name="Model.extension" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="220" name="Extension" >
+     <UML:Operation visibility="public" xmi.id="1143" type="void" name="AddObject" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ObjectfromExtension" name="object" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1144" type="void" name="Destroy" />
+     <UML:Operation visibility="public" xmi.id="1145" type="ObjectfromExtension" name="FindObject" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1146" type="void" name="forward" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="*.args" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1147" type="bool" name="HasObjects" />
+     <UML:Operation visibility="public" xmi.id="1148" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1149" type="ObjectfromExtension[]" name="Objects" />
+     <UML:Operation visibility="public" xmi.id="1150" type="void" name="RemoveObject" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ObjectfromExtension" name="object" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1151" type="string[]" name="TreeInfo" />
+     <UML:Operation visibility="public" xmi.id="1152" type="void" name="UnsetModified" />
+     <UML:Operation visibility="public" xmi.id="1153" type="int" name="WasModified" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="224" name="Model.layer" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="225" name="BaseLayer" >
+     <UML:Operation visibility="public" xmi.id="931" type="Projection" name="GetProjection" />
+     <UML:Operation visibility="public" xmi.id="932" type="bool" name="HasClassification" />
+     <UML:Operation visibility="public" xmi.id="933" type="bool" name="HasShapes" />
+     <UML:Operation visibility="public" xmi.id="934" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+      <UML:Parameter visibility="public" xmi.id="2" value="True" type="bool" name="visible" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="Projection" name="projection" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="935" type="void" name="SetProjection" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Projection" name="projection" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="936" type="void" name="SetVisible" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="bool" name="visible" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="937" type="bool" name="Visible" />
+    </UML:Class>
+    <UML:Class stereotype="1365" visibility="public" xmi.id="226" name="Layer" >
+     <UML:Operation visibility="public" xmi.id="943" type="tuple(int,int,int,int)" name="BoundingBox" />
+     <UML:Operation visibility="public" xmi.id="944" type="void" name="_classification_changed" />
+     <UML:Operation visibility="public" xmi.id="945" type="tuple(int,int,int,int)" name="ClipBoundingBox" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="tuple(int,int,int,int)" name="bbox" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="946" type="void" name="Destroy" />
+     <UML:Operation visibility="public" xmi.id="947" type="string" name="GetClassificationColumn" />
+     <UML:Operation visibility="public" xmi.id="948" type="Classification" name="GetClassification" />
+     <UML:Operation visibility="public" xmi.id="949" type="Column.type" name="GetFieldType" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="fieldName" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="950" type="bool" name="HasClassification" />
+     <UML:Operation visibility="public" xmi.id="951" type="bool" name="HasShapes" />
+     <UML:Operation visibility="public" xmi.id="952" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="Shape data" name="data" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="Projection" name="projection" />
+      <UML:Parameter visibility="public" xmi.id="4" value="Transparent" type="Color" name="fill" />
+      <UML:Parameter visibility="public" xmi.id="5" value="Black" type="Color" name="stroke" />
+      <UML:Parameter visibility="public" xmi.id="6" value="1" type="int" name="lineWidth" />
+      <UML:Parameter visibility="public" xmi.id="7" value="True" type="bool" name="visible" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="953" type="bbox" name="LatLongBoundingBox" />
+     <UML:Operation visibility="public" xmi.id="954" type="int" name="NumShapes" />
+     <UML:Operation visibility="public" xmi.id="955" type="void" name="SetClassificationColumn" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="column" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="956" type="void" name="SetClassification" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Classification" name="clazz" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="957" type="void" name="SetShapeStore" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="shapestore" name="store" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="958" type="tuple(int,int,int,int)" name="ShapesBoundingBox" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="shapes" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="959" type="Shape" name="Shapes" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="index" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="960" type="Shapes" name="ShapesInRegion" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="tuple(int,int,int,int)" name="bbox" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="962" type="shapestore" name="ShapeStore" />
+     <UML:Operation visibility="public" xmi.id="963" type="constanten" name="ShapeType" />
+     <UML:Operation visibility="public" xmi.id="964" type="string()" name="TreeInfo" />
+    </UML:Class>
+    <UML:Class stereotype="1365" visibility="public" xmi.id="227" name="RasterLayer" >
+     <UML:Operation visibility="public" xmi.id="938" type="tuple(int,int,int,int))" name="BoundingBox" />
+     <UML:Operation visibility="public" xmi.id="939" type="string" name="GetImageFilename" />
+     <UML:Operation visibility="public" xmi.id="940" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="string" name="filename" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="Projection" name="projection" />
+      <UML:Parameter visibility="public" xmi.id="4" value="True" type="bool" name="visible" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="941" type="tuple(int,int,int,int)" name="LatLongBox" />
+     <UML:Operation visibility="public" xmi.id="942" type="tuple(string, array(string))" name="TreeInfo" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="232" name="Model.map" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="233" name="Map" >
+     <UML:Operation visibility="public" xmi.id="1060" type="void" name="AddLayer" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1061" type="int4" name="BoundingBox" />
+     <UML:Operation visibility="public" xmi.id="1062" type="int" name="CanRemoveLayer" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1063" type="void" name="ClearLayers" />
+     <UML:Operation visibility="public" xmi.id="1064" type="void" name="Destroy" />
+     <UML:Operation visibility="public" xmi.id="1065" type="void" name="forward" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="*args" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1066" type="Projection" name="GetProjection" />
+     <UML:Operation visibility="public" xmi.id="1067" type="bool" name="HasLayers" />
+     <UML:Operation visibility="public" xmi.id="1068" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+      <UML:Parameter visibility="public" xmi.id="2" value="None" type="Projection" name="projection" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1069" type="LabelLayer" name="LabelLayer" />
+     <UML:Operation visibility="public" xmi.id="1070" type="Layer[]" name="Layers" />
+     <UML:Operation visibility="public" xmi.id="1071" type="void" name="LowerLayer" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1072" type="void" name="MoveLayerToBottom" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1073" type="void" name="MoveLayerToTop" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1074" type="int4" name="ProjectedBoundingBox" />
+     <UML:Operation visibility="public" xmi.id="1075" type="void" name="RaiseLayer" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1076" type="void" name="RemoveLayer" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1077" type="void" name="SetProjection" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Projection" name="projection" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1078" type="void" name="subscribe_layer_channels" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1079" type="void" name="TreeInfo" />
+     <UML:Operation visibility="public" xmi.id="1080" type="void" name="UnsetModified" />
+     <UML:Operation visibility="public" xmi.id="1081" type="void" name="unsubscribe_layer_channels" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Layer" name="layer" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1082" type="string()" name="WasModified" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="236" name="Model.proj" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="237" name="BaseProjection" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="238" name="ProjFile" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="733" name="Projection" >
+     <UML:Operation visibility="public" xmi.id="991" type="string" name="EPSGCode" />
+     <UML:Operation visibility="public" xmi.id="992" type="int()" name="ForwardBBox" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int()" name="bbox" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="993" type="string[]" name="GetAllParameters" />
+     <UML:Operation visibility="public" xmi.id="994" type="string" name="GetName" />
+     <UML:Operation visibility="public" xmi.id="995" type="string" name="GetParameter" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="param" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="996" type="int" name="GetProjectedUnits" />
+     <UML:Operation visibility="public" xmi.id="997" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="stinr[]" name="params" />
+      <UML:Parameter visibility="public" xmi.id="2" value="None" type="string" name="name" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="string" name="epsg" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="998" type="int()" name="InverseBBox" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int()" name="bbox" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="999" type="string" name="Label" />
+     <UML:Operation visibility="public" xmi.id="1000" type="string" name="__repr__" />
+     <UML:Operation visibility="public" xmi.id="1001" type="int(4)" name="_transform_bbox" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Trafo" name="trafo" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="int(4)" name="bbox" />
+     </UML:Operation>
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="239" name="Model.session" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="240" name="AutoRemoveDir" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="241" name="AutoRemoveFile" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="242" name="Session" >
+     <UML:Operation visibility="public" xmi.id="1083" type="void" name="AddDBConnection" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="PostGISConnection" name="dbconn" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1084" type="void" name="AddExtension" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Extension" name="extension" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1085" type="void" name="AddMap" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Map" name="map" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1086" type="void" name="AddShapeStore" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ShapefileStore" name="shapestore" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1087" type="void" name="_add_shapestore" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="ShapefileStore" name="store" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1088" type="void" name="AddTable" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="AutoTransientTable" name="table" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1089" type="int" name="CanRemoveDBConnection" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="PostGISConnection" name="dbconn" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1090" type="void" name="changed" >
+      <UML:Parameter visibility="public" xmi.id="1" value="None" type="" name="channel" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="" name="*args" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1091" type="void" name="_clean_weak_store_refs" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="weakref" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1092" type="data containers" name="DataContainers" />
+     <UML:Operation visibility="public" xmi.id="1093" type="PostGISConnection" name="DBConnections" />
+     <UML:Operation visibility="public" xmi.id="1094" type="void" name="Destroy" />
+     <UML:Operation visibility="public" xmi.id="1095" type="Extension[]" name="Extensions" />
+     <UML:Operation visibility="public" xmi.id="1096" type="void" name="forward" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="" name="*args" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1097" type="int" name="HasDBConnections" />
+     <UML:Operation visibility="public" xmi.id="1098" type="int" name="HasExtensions" />
+     <UML:Operation visibility="public" xmi.id="1099" type="int" name="HasMaps" />
+     <UML:Operation visibility="public" xmi.id="1100" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="title" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1101" type="Map[]" name="Maps" />
+     <UML:Operation visibility="public" xmi.id="1102" type="ShapefileStore" name="OpenDBShapeStore" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="PostGISConnection" name="db" />
+      <UML:Parameter visibility="public" xmi.id="2" value="" type="string" name="tablename" />
+      <UML:Parameter visibility="public" xmi.id="3" value="None" type="string" name="id_column" />
+      <UML:Parameter visibility="public" xmi.id="4" value="None" type="string" name="geometry_column" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1103" type="ShapefileStore" name="OpenShapefile" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="filename" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1104" type="DBFTable" name="OpenTableFile" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="filename" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1105" type="void" name="RemoveDBConnection" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="PostGISConnection" name="dbconn" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1106" type="void" name="RemoveMap" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Map" name="map" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1107" type="void" name="RemoveTable" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="*Table" name="table" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1108" type="void" name="SetFilename" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="filename" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1109" type="ShapefileStore[]" name="ShapeStores" />
+     <UML:Operation visibility="public" xmi.id="1110" type="*Tables[]" name="Tables" />
+     <UML:Operation visibility="public" xmi.id="1111" type="string" name="temp_directory" />
+     <UML:Operation visibility="public" xmi.id="1112" type="TransientDatabase" name="TransientDB" />
+     <UML:Operation visibility="public" xmi.id="1113" type="string[]" name="TreeInfo" />
+     <UML:Operation visibility="public" xmi.id="1114" type="*Tables[]" name="UnreferencedTables" />
+     <UML:Operation visibility="public" xmi.id="1115" type="void" name="UnsetModified" />
+     <UML:Operation visibility="public" xmi.id="1116" type="int" name="WasModified" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="261" name="Model.range" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="262" name="Range" >
+     <UML:Operation visibility="public" xmi.id="1223" type="bool" name="__contains__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="int" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1224" type="bool" name="__eq__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Range" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1225" type="string" name="_float2string" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="float" name="value" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1226" type="string4" name="GetRange" />
+     <UML:Operation visibility="public" xmi.id="1227" type="void" name="__init__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="None" type="string" name="range" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1228" type="void" name="__ne__" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="Range" name="other" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1229" type="void" name="_SetRange" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="string" name="range" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1230" type="string" name="string" >
+      <UML:Parameter visibility="public" xmi.id="1" value="" type="tuple(string,int,int,string)" name="range" />
+     </UML:Operation>
+     <UML:Operation visibility="public" xmi.id="1231" type="string" name="__str__" />
+    </UML:Class>
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="264" name="Model.data" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="265" name="DerivedShapeStore" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="266" name="ShapefileShape" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="267" name="ShapefileStore" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="268" name="ShapeTable" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="269" name="Model.load" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="270" name="AttrDesc" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="271" name="LoadCancelled" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="272" name="LoadError" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="273" name="SessionLoader" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="280" name="Model.classgen" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="281" name="CustomRamp" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="282" name="FixedRamp" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="283" name="HotToColdRamp" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="284" name="MonochromaticRamp" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="285" name="Model.postgisdb" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="286" name="ConnectionError" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="287" name="PostGISColumn" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="288" name="PostGISConnection" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="289" name="PostGISShape" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="291" name="PostGISTable" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="825" name="PostGISShapeStore" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="292" name="Model.resource" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="293" name="ProjFileReader" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="294" name="ProjFileSaver" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="295" name="Model.save" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="296" name="SessionSaver" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="297" name="Model.scalebar" />
+   <UML:Package visibility="public" xmi.id="298" name="Model.table" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="299" name="DBFColumn" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="300" name="DBFTable" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="301" name="MemoryColumn" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="302" name="MemoryTable" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="303" name="Model.transientdb" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="304" name="AutoTransientTable" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="305" name="ColiumnReference" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="306" name="TransientDatabase" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="307" name="TransientJoinedTable" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="308" name="TransientTableBase" />
+    <UML:Class stereotype="1365" visibility="public" xmi.id="309" name="TransientTable" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="310" name="Model.wellknowntext" />
+   <UML:Package visibility="public" xmi.id="311" name="Model.xmlreader" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="313" name="XMLReader" />
+   </UML:Package>
+   <UML:Package visibility="public" xmi.id="312" name="Model.xmlwriter" >
+    <UML:Class stereotype="1365" visibility="public" xmi.id="314" name="XMLWriter" />
+   </UML:Package>
+   <UML:Association visibility="public" xmi.id="201" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="200" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="195" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="202" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="194" />
+     <UML:AssociationEndRole visibility="public" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="203" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="200" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="206" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="194" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="189" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="221" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="220" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="195" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="222" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="220" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="228" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="225" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="229" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="225" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="195" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="230" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="226" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="225" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="231" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="227" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="225" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="234" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="233" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="235" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="233" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="195" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="243" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="242" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="194" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="244" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="242" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="195" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="251" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="210" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="208" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="252" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="212" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="208" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="253" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="213" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="208" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="254" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="214" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="189" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="263" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="218" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="217" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="316" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="195" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="189" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="318" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="233" />
+     <UML:AssociationEndRole visibility="public" type="233" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="341" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="none" type="227" />
+     <UML:AssociationEndRole visibility="public" isNavigable="true" type="226" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Generalization child="194" visibility="public" xmi.id="600" parent="189" />
+   <UML:Generalization child="200" visibility="public" xmi.id="602" parent="195" />
+   <UML:Generalization child="200" visibility="public" xmi.id="603" parent="194" />
+   <UML:Association visibility="public" xmi.id="605" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="200" />
+     <UML:AssociationEndRole visibility="public" type="199" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Generalization child="225" visibility="public" xmi.id="615" parent="195" />
+   <UML:Generalization child="225" visibility="public" xmi.id="616" parent="194" />
+   <UML:Generalization child="220" visibility="public" xmi.id="625" parent="194" />
+   <UML:Generalization child="220" visibility="public" xmi.id="626" parent="195" />
+   <UML:Generalization child="233" visibility="public" xmi.id="645" parent="194" />
+   <UML:Generalization child="233" visibility="public" xmi.id="646" parent="195" />
+   <UML:Generalization child="242" visibility="public" xmi.id="655" parent="194" />
+   <UML:Generalization child="242" visibility="public" xmi.id="656" parent="195" />
+   <UML:Generalization child="227" visibility="public" xmi.id="669" parent="225" />
+   <UML:Generalization child="226" visibility="public" xmi.id="670" parent="225" />
+   <UML:Generalization child="214" visibility="public" xmi.id="679" parent="189" />
+   <UML:Association visibility="public" xmi.id="681" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="214" />
+     <UML:AssociationEndRole visibility="public" type="208" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Generalization child="209" visibility="public" xmi.id="695" parent="208" />
+   <UML:Generalization child="212" visibility="public" xmi.id="705" parent="208" />
+   <UML:Generalization child="213" visibility="public" xmi.id="706" parent="208" />
+   <UML:Association visibility="public" xmi.id="708" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="226" />
+     <UML:AssociationEndRole visibility="public" type="214" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="715" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="208" />
+     <UML:AssociationEndRole visibility="public" type="211" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="716" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="211" />
+     <UML:AssociationEndRole visibility="public" type="217" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="721" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="composite" type="242" />
+     <UML:AssociationEndRole visibility="public" type="233" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="722" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="242" />
+     <UML:AssociationEndRole visibility="public" type="220" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="731" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="composite" type="233" />
+     <UML:AssociationEndRole visibility="public" type="226" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="732" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="composite" type="233" />
+     <UML:AssociationEndRole visibility="public" type="227" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="816" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="212" />
+     <UML:AssociationEndRole visibility="public" type="262" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="1058" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="233" />
+     <UML:AssociationEndRole visibility="public" type="733" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="1059" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="226" />
+     <UML:AssociationEndRole visibility="public" type="733" />
+    </UML:Association.connection>
+   </UML:Association>
+   <UML:Association visibility="public" xmi.id="1263" >
+    <UML:Association.connection>
+     <UML:AssociationEndRole visibility="public" aggregation="shared" type="214" />
+     <UML:AssociationEndRole visibility="public" type="217" />
+    </UML:Association.connection>
+   </UML:Association>
+  </UML:Model>
+ </XMI.content>
+ <XMI.extensions xmi.extender="umbrello" >
+  <docsettings viewid="174" documentation="" uniqueid="1379" />
+  <diagrams>
+   <diagram snapgrid="1" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="64" showgrid="1" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="5063" snapy="10" showatts="1" xmi.id="174" documentation="" type="402" showops="1" showpackage="0" name="class diagram" localid="30000" showstereotype="0" showscope="1" snapcsgrid="1" font="helvetica,12,-1,0,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="2869" >
+    <widgets>
+     <classwidget usesdiagramfillcolour="0" width="430" showattsigs="601" usesdiagramusefillcolour="0" x="2425" linecolour="#ff0000" y="410" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="120" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="194" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="240" showattsigs="601" usesdiagramusefillcolour="0" x="3090" linecolour="#ff0000" y="410" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="100" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="195" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="1" width="230" showattsigs="601" usesdiagramusefillcolour="1" x="2495" linecolour="none" y="170" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="1" fillcolour="none" height="40" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="189" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="helvetica,12,-1,0,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="710" showattsigs="601" usesdiagramusefillcolour="0" x="4325" linecolour="#ff0000" y="1010" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="140" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="200" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="580" showattsigs="601" usesdiagramusefillcolour="0" x="4390" linecolour="#ff0000" y="1220" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="60" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="199" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="640" showattsigs="601" usesdiagramusefillcolour="0" x="3660" linecolour="#ff0000" y="1010" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="180" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="225" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="420" showattsigs="601" usesdiagramusefillcolour="0" x="1540" linecolour="#ff0000" y="1015" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="270" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="220" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="430" showattsigs="601" usesdiagramusefillcolour="0" x="1035" linecolour="#ff0000" y="1010" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="580" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="214" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="480" showattsigs="601" usesdiagramusefillcolour="0" x="3160" linecolour="#ff0000" y="1010" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="520" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="233" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="1110" showattsigs="601" usesdiagramusefillcolour="0" x="2005" linecolour="#ff0000" y="1015" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="750" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="242" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="1310" showattsigs="601" usesdiagramusefillcolour="0" x="3505" linecolour="#ff0000" y="1770" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="480" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="226" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="770" showattsigs="601" usesdiagramusefillcolour="0" x="4235" linecolour="#ff0000" y="1530" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="140" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="227" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="780" showattsigs="601" usesdiagramusefillcolour="0" x="890" linecolour="#ff0000" y="1855" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="290" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="208" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="780" showattsigs="601" usesdiagramusefillcolour="0" x="1170" linecolour="#ff0000" y="2230" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="180" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="209" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="430" showattsigs="601" usesdiagramusefillcolour="0" x="2385" linecolour="#ff0000" y="2535" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="310" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="211" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="1100" showattsigs="601" usesdiagramusefillcolour="0" x="790" linecolour="#ff0000" y="2515" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="330" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="212" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="910" showattsigs="601" usesdiagramusefillcolour="0" x="2285" linecolour="#ff0000" y="1980" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="220" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="213" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="300" showattsigs="601" usesdiagramusefillcolour="0" x="880" linecolour="#ff0000" y="1700" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="100" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="215" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="380" showattsigs="601" usesdiagramusefillcolour="0" x="2590" linecolour="#ff0000" y="2260" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="140" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="217" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="250" showattsigs="601" usesdiagramusefillcolour="0" x="2835" linecolour="#ff0000" y="2530" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="120" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="218" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="610" showattsigs="601" usesdiagramusefillcolour="0" x="3125" linecolour="#ff0000" y="2485" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="270" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="733" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+     <classwidget usesdiagramfillcolour="0" width="400" showattsigs="601" usesdiagramusefillcolour="0" x="1950" linecolour="#ff0000" y="2570" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="220" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="262" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Bitstream Charter,12,-1,5,75,0,0,0,0,0" />
+    </widgets>
+    <messages/>
+    <associations>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" widgetbid="189" widgetaid="194" xmi.id="600" >
+      <linepath>
+       <startpoint startx="2640" starty="410" />
+       <endpoint endx="2650" endy="210" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="6" indexb="5" widgetbid="195" widgetaid="200" xmi.id="602" >
+      <linepath>
+       <startpoint startx="4800" starty="1010" />
+       <endpoint endx="3290" endy="510" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="1" totalcountb="6" indexb="5" widgetbid="194" widgetaid="200" xmi.id="603" >
+      <linepath>
+       <startpoint startx="4560" starty="1010" />
+       <endpoint endx="2780" endy="530" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="199" widgetaid="200" xmi.id="605" >
+      <linepath>
+       <startpoint startx="4680" starty="1150" />
+       <endpoint endx="4680" endy="1220" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="6" indexb="4" widgetbid="195" widgetaid="225" xmi.id="615" >
+      <linepath>
+       <startpoint startx="4090" starty="1010" />
+       <endpoint endx="3250" endy="510" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="1" totalcountb="6" indexb="4" widgetbid="194" widgetaid="225" xmi.id="616" >
+      <linepath>
+       <startpoint startx="3870" starty="1010" />
+       <endpoint endx="2710" endy="530" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="6" indexb="1" widgetbid="194" widgetaid="220" xmi.id="625" >
+      <linepath>
+       <startpoint startx="1820" starty="1015" />
+       <endpoint endx="2500" endy="530" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="1" totalcountb="6" indexb="1" widgetbid="195" widgetaid="220" xmi.id="626" >
+      <linepath>
+       <startpoint startx="1680" starty="1015" />
+       <endpoint endx="3130" endy="510" />
+       <point x="1860" y="980" />
+       <point x="2660" y="690" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="1" totalcountb="6" indexb="3" widgetbid="194" widgetaid="233" xmi.id="645" >
+      <linepath>
+       <startpoint startx="3320" starty="1010" />
+       <endpoint endx="2640" endy="530" />
+       <point x="3060" y="840" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="6" indexb="3" widgetbid="195" widgetaid="233" xmi.id="646" >
+      <linepath>
+       <startpoint startx="3480" starty="1010" />
+       <endpoint endx="3210" endy="510" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="1" totalcountb="6" indexb="2" widgetbid="194" widgetaid="242" xmi.id="655" >
+      <linepath>
+       <startpoint startx="2380" starty="1015" />
+       <endpoint endx="2570" endy="530" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="6" indexb="2" widgetbid="195" widgetaid="242" xmi.id="656" >
+      <linepath>
+       <startpoint startx="2750" starty="1015" />
+       <endpoint endx="3170" endy="510" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" widgetbid="225" widgetaid="227" xmi.id="669" >
+      <linepath>
+       <startpoint startx="4620" starty="1530" />
+       <endpoint endx="4090" endy="1190" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" widgetbid="225" widgetaid="226" xmi.id="670" >
+      <linepath>
+       <startpoint startx="4160" starty="1770" />
+       <endpoint endx="3870" endy="1190" />
+       <point x="4120" y="1960" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" widgetbid="189" widgetaid="214" xmi.id="679" >
+      <linepath>
+       <startpoint startx="1250" starty="1010" />
+       <endpoint endx="2570" endy="210" />
+       <point x="1250" y="980" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="2" indexb="1" widgetbid="208" widgetaid="214" xmi.id="681" >
+      <linepath>
+       <startpoint startx="1320" starty="1590" />
+       <endpoint endx="1280" endy="1855" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" widgetbid="208" widgetaid="209" xmi.id="695" >
+      <linepath>
+       <startpoint startx="1560" starty="2230" />
+       <endpoint endx="1410" endy="2145" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" widgetbid="208" widgetaid="212" xmi.id="705" >
+      <linepath>
+       <startpoint startx="1340" starty="2515" />
+       <endpoint endx="1150" endy="2145" />
+       <point x="1150" y="2440" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" widgetbid="208" widgetaid="213" xmi.id="706" >
+      <linepath>
+       <startpoint startx="2285" starty="2090" />
+       <endpoint endx="1670" endy="1950" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="3" indexb="1" widgetbid="214" widgetaid="215" roleBdoc="" documentation="" roleAdoc="" type="503" changeabilityA="900" changeabilityB="900" visibilityA="200" >
+      <linepath>
+       <startpoint startx="1030" starty="1700" />
+       <endpoint endx="1180" endy="1590" />
+       <point x="1140" y="1640" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="3" indexb="1" widgetbid="214" widgetaid="226" xmi.id="708" >
+      <linepath>
+       <startpoint startx="3505" starty="2090" />
+       <endpoint endx="1465" endy="1200" />
+       <point x="1940" y="1870" />
+      </linepath>
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="5" linecolour="none" y="1965" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1367" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="1465" linecolour="none" y="1205" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1368" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="3" indexb="1" widgetbid="211" widgetaid="208" xmi.id="715" >
+      <linepath>
+       <startpoint startx="1670" starty="2050" />
+       <endpoint endx="2530" endy="2535" />
+       <point x="1890" y="2080" />
+       <point x="2090" y="2370" />
+       <point x="2360" y="2460" />
+      </linepath>
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="1675" linecolour="none" y="2045" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1369" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="2495" linecolour="none" y="2495" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1370" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="3" indexb="1" widgetbid="217" widgetaid="211" xmi.id="716" >
+      <linepath>
+       <startpoint startx="2670" starty="2535" />
+       <endpoint endx="2720" endy="2400" />
+      </linepath>
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="2665" linecolour="none" y="2495" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1371" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="2685" linecolour="none" y="2405" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1372" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="3" indexb="2" widgetbid="217" widgetaid="218" roleBdoc="" documentation="" roleAdoc="" type="503" changeabilityA="900" changeabilityB="900" visibilityA="200" >
+      <linepath>
+       <startpoint startx="2960" starty="2530" />
+       <endpoint endx="2840" endy="2400" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="233" widgetaid="242" xmi.id="721" >
+      <linepath>
+       <startpoint startx="3115" starty="1390" />
+       <endpoint endx="3160" endy="1270" />
+      </linepath>
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="5" linecolour="none" y="1335" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1373" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="5" linecolour="none" y="1265" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1374" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="220" widgetaid="242" xmi.id="722" >
+      <linepath>
+       <startpoint startx="2005" starty="1390" />
+       <endpoint endx="1750" endy="1285" />
+       <point x="1810" y="1370" />
+      </linepath>
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="1965" linecolour="none" y="1355" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1375" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="1755" linecolour="none" y="1285" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1376" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="3" indexb="1" widgetbid="226" widgetaid="233" xmi.id="731" >
+      <linepath>
+       <startpoint startx="3480" starty="1530" />
+       <endpoint endx="3505" endy="1930" />
+       <point x="3810" y="1940" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="227" widgetaid="233" xmi.id="732" >
+      <linepath>
+       <startpoint startx="3640" starty="1270" />
+       <endpoint endx="4235" endy="1600" />
+       <point x="4200" y="1570" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="262" widgetaid="212" xmi.id="816" >
+      <linepath>
+       <startpoint startx="1890" starty="2680" />
+       <endpoint endx="1950" endy="2680" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="1" totalcountb="3" indexb="1" widgetbid="733" widgetaid="233" xmi.id="1058" >
+      <linepath>
+       <startpoint startx="3320" starty="1530" />
+       <endpoint endx="3330" endy="2485" />
+      </linepath>
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="5" linecolour="none" y="1505" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="709" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1377" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+      <floatingtext usesdiagramfillcolour="1" width="30" usesdiagramusefillcolour="1" x="5" linecolour="none" y="2455" linewidth="none" usesdiagramlinewidth="1" posttext="" usesdiagramlinecolour="1" role="710" fillcolour="none" height="30" usefillcolor="1" pretext="+" isinstance="0" xmi.id="1378" text="" font="Bitstream Charter,12,-1,5,50,0,0,0,0,0" />
+     </assocwidget>
+     <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" widgetbid="733" widgetaid="226" xmi.id="1059" >
+      <linepath>
+       <startpoint startx="4160" starty="2250" />
+       <endpoint endx="3530" endy="2485" />
+      </linepath>
+     </assocwidget>
+     <assocwidget totalcounta="3" indexa="2" totalcountb="2" indexb="1" widgetbid="217" widgetaid="214" xmi.id="1263" >
+      <linepath>
+       <startpoint startx="1465" starty="1400" />
+       <endpoint endx="2590" endy="2330" />
+       <point x="1920" y="1990" />
+       <point x="2150" y="2320" />
+      </linepath>
+     </assocwidget>
+    </associations>
+   </diagram>
+  </diagrams>
+  <listview>
+   <listitem open="1" type="800" id="-1" label="Ansichten" >
+    <listitem open="1" type="801" id="-1" label="Logische Ansicht" >
+     <listitem open="0" type="803" id="187" label="Lib Paket" />
+     <listitem open="1" type="803" id="192" label="Modul Paket" />
+     <listitem open="0" type="807" id="174" label="class diagram" />
+     <listitem open="0" type="818" id="188" >
+      <listitem open="1" type="813" id="189" />
+     </listitem>
+     <listitem open="1" type="818" id="186" >
+      <listitem open="1" type="813" id="194" >
+       <listitem open="0" type="815" id="889" />
+       <listitem open="0" type="815" id="892" />
+       <listitem open="0" type="815" id="891" />
+       <listitem open="0" type="815" id="890" />
+      </listitem>
+      <listitem open="1" type="813" id="195" >
+       <listitem open="0" type="815" id="921" />
+       <listitem open="0" type="815" id="920" />
+       <listitem open="0" type="815" id="919" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="818" id="280" >
+      <listitem open="1" type="813" id="281" />
+      <listitem open="1" type="813" id="282" />
+      <listitem open="1" type="813" id="283" />
+      <listitem open="1" type="813" id="284" />
+     </listitem>
+     <listitem open="1" type="818" id="207" >
+      <listitem open="1" type="813" id="208" >
+       <listitem open="0" type="815" id="1185" />
+       <listitem open="0" type="815" id="1186" />
+       <listitem open="0" type="815" id="1187" />
+       <listitem open="0" type="815" id="1189" />
+       <listitem open="0" type="815" id="1190" />
+       <listitem open="0" type="815" id="1193" />
+       <listitem open="0" type="815" id="1194" />
+       <listitem open="0" type="815" id="1195" />
+       <listitem open="0" type="815" id="1184" />
+       <listitem open="0" type="815" id="1188" />
+       <listitem open="0" type="815" id="1191" />
+       <listitem open="0" type="815" id="1192" />
+      </listitem>
+      <listitem open="1" type="813" id="209" >
+       <listitem open="0" type="815" id="1199" />
+       <listitem open="0" type="815" id="1201" />
+       <listitem open="0" type="815" id="1196" />
+       <listitem open="0" type="815" id="1197" />
+       <listitem open="0" type="815" id="1198" />
+       <listitem open="0" type="815" id="1200" />
+       <listitem open="0" type="815" id="1202" />
+      </listitem>
+      <listitem open="1" type="813" id="210" />
+      <listitem open="1" type="813" id="211" >
+       <listitem open="0" type="815" id="1244" />
+       <listitem open="0" type="815" id="1245" />
+       <listitem open="0" type="815" id="1246" />
+       <listitem open="0" type="815" id="1250" />
+       <listitem open="0" type="815" id="1251" />
+       <listitem open="0" type="815" id="1252" />
+       <listitem open="0" type="815" id="1253" />
+       <listitem open="0" type="815" id="1241" />
+       <listitem open="0" type="815" id="1242" />
+       <listitem open="0" type="815" id="1243" />
+       <listitem open="0" type="815" id="1247" />
+       <listitem open="0" type="815" id="1248" />
+       <listitem open="0" type="815" id="1249" />
+      </listitem>
+      <listitem open="1" type="813" id="212" >
+       <listitem open="0" type="815" id="1212" />
+       <listitem open="0" type="815" id="1213" />
+       <listitem open="0" type="815" id="1214" />
+       <listitem open="0" type="815" id="1215" />
+       <listitem open="0" type="815" id="1216" />
+       <listitem open="0" type="815" id="1218" />
+       <listitem open="0" type="815" id="1220" />
+       <listitem open="0" type="815" id="1221" />
+       <listitem open="0" type="815" id="1222" />
+       <listitem open="0" type="815" id="1209" />
+       <listitem open="0" type="815" id="1210" />
+       <listitem open="0" type="815" id="1211" />
+       <listitem open="0" type="815" id="1217" />
+       <listitem open="0" type="815" id="1219" />
+      </listitem>
+      <listitem open="1" type="813" id="213" >
+       <listitem open="0" type="815" id="1235" />
+       <listitem open="0" type="815" id="1236" />
+       <listitem open="0" type="815" id="1238" />
+       <listitem open="0" type="815" id="1240" />
+       <listitem open="0" type="815" id="1232" />
+       <listitem open="0" type="815" id="1233" />
+       <listitem open="0" type="815" id="1234" />
+       <listitem open="0" type="815" id="1237" />
+       <listitem open="0" type="815" id="1239" />
+      </listitem>
+      <listitem open="1" type="813" id="215" >
+       <listitem open="0" type="815" id="1181" />
+       <listitem open="0" type="815" id="1182" />
+       <listitem open="0" type="815" id="1183" />
+      </listitem>
+      <listitem open="1" type="813" id="214" >
+       <listitem open="0" type="815" id="1154" />
+       <listitem open="0" type="815" id="1160" />
+       <listitem open="0" type="815" id="1162" />
+       <listitem open="0" type="815" id="1163" />
+       <listitem open="0" type="815" id="1164" />
+       <listitem open="0" type="815" id="1165" />
+       <listitem open="0" type="815" id="1166" />
+       <listitem open="0" type="815" id="1167" />
+       <listitem open="0" type="815" id="1168" />
+       <listitem open="0" type="815" id="1170" />
+       <listitem open="0" type="815" id="1172" />
+       <listitem open="0" type="815" id="1173" />
+       <listitem open="0" type="815" id="1175" />
+       <listitem open="0" type="815" id="1177" />
+       <listitem open="0" type="815" id="1178" />
+       <listitem open="0" type="815" id="1179" />
+       <listitem open="0" type="815" id="1180" />
+       <listitem open="0" type="815" id="1174" />
+       <listitem open="0" type="815" id="1159" />
+       <listitem open="0" type="815" id="1161" />
+       <listitem open="0" type="815" id="1169" />
+       <listitem open="0" type="815" id="1171" />
+       <listitem open="0" type="815" id="1157" />
+       <listitem open="0" type="815" id="1158" />
+       <listitem open="0" type="815" id="1155" />
+       <listitem open="0" type="815" id="1156" />
+      </listitem>
+     </listitem>
+     <listitem open="1" type="818" id="216" >
+      <listitem open="1" type="813" id="217" >
+       <listitem open="0" type="815" id="1258" />
+       <listitem open="0" type="815" id="1260" />
+       <listitem open="0" type="815" id="1261" />
+       <listitem open="0" type="815" id="1262" />
+       <listitem open="0" type="815" id="1259" />
+      </listitem>
+      <listitem open="1" type="813" id="218" >
+       <listitem open="0" type="815" id="1254" />
+       <listitem open="0" type="815" id="1256" />
+       <listitem open="0" type="815" id="1257" />
+       <listitem open="0" type="815" id="1255" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="818" id="264" >
+      <listitem open="1" type="813" id="265" />
+      <listitem open="1" type="813" id="268" />
+      <listitem open="1" type="813" id="266" />
+      <listitem open="1" type="813" id="267" />
+     </listitem>
+     <listitem open="1" type="818" id="219" >
+      <listitem open="1" type="813" id="220" >
+       <listitem open="0" type="815" id="1143" />
+       <listitem open="0" type="815" id="1144" />
+       <listitem open="0" type="815" id="1145" />
+       <listitem open="0" type="815" id="1147" />
+       <listitem open="0" type="815" id="1149" />
+       <listitem open="0" type="815" id="1150" />
+       <listitem open="0" type="815" id="1151" />
+       <listitem open="0" type="815" id="1152" />
+       <listitem open="0" type="815" id="1153" />
+       <listitem open="0" type="815" id="1148" />
+       <listitem open="0" type="815" id="1146" />
+      </listitem>
+     </listitem>
+     <listitem open="1" type="818" id="198" >
+      <listitem open="1" type="813" id="199" >
+       <listitem open="0" type="815" id="928" />
+      </listitem>
+      <listitem open="1" type="813" id="200" >
+       <listitem open="0" type="815" id="923" />
+       <listitem open="0" type="815" id="924" />
+       <listitem open="0" type="815" id="926" />
+       <listitem open="0" type="815" id="927" />
+       <listitem open="0" type="815" id="925" />
+      </listitem>
+     </listitem>
+     <listitem open="1" type="818" id="224" >
+      <listitem open="1" type="813" id="225" >
+       <listitem open="0" type="815" id="931" />
+       <listitem open="0" type="815" id="932" />
+       <listitem open="0" type="815" id="933" />
+       <listitem open="0" type="815" id="935" />
+       <listitem open="0" type="815" id="936" />
+       <listitem open="0" type="815" id="937" />
+       <listitem open="0" type="815" id="934" />
+      </listitem>
+      <listitem open="1" type="813" id="226" >
+       <listitem open="0" type="815" id="943" />
+       <listitem open="0" type="815" id="945" />
+       <listitem open="0" type="815" id="946" />
+       <listitem open="0" type="815" id="948" />
+       <listitem open="0" type="815" id="947" />
+       <listitem open="0" type="815" id="949" />
+       <listitem open="0" type="815" id="950" />
+       <listitem open="0" type="815" id="951" />
+       <listitem open="0" type="815" id="953" />
+       <listitem open="0" type="815" id="954" />
+       <listitem open="0" type="815" id="956" />
+       <listitem open="0" type="815" id="955" />
+       <listitem open="0" type="815" id="957" />
+       <listitem open="0" type="815" id="962" />
+       <listitem open="0" type="815" id="963" />
+       <listitem open="0" type="815" id="959" />
+       <listitem open="0" type="815" id="958" />
+       <listitem open="0" type="815" id="960" />
+       <listitem open="0" type="815" id="964" />
+       <listitem open="0" type="815" id="952" />
+       <listitem open="0" type="815" id="944" />
+      </listitem>
+      <listitem open="1" type="813" id="227" >
+       <listitem open="0" type="815" id="938" />
+       <listitem open="0" type="815" id="939" />
+       <listitem open="0" type="815" id="941" />
+       <listitem open="0" type="815" id="942" />
+       <listitem open="0" type="815" id="940" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="818" id="269" >
+      <listitem open="1" type="813" id="270" />
+      <listitem open="1" type="813" id="271" />
+      <listitem open="1" type="813" id="272" />
+      <listitem open="1" type="813" id="273" />
+     </listitem>
+     <listitem open="1" type="818" id="232" >
+      <listitem open="1" type="813" id="233" >
+       <listitem open="0" type="815" id="1060" />
+       <listitem open="0" type="815" id="1061" />
+       <listitem open="0" type="815" id="1062" />
+       <listitem open="0" type="815" id="1063" />
+       <listitem open="0" type="815" id="1064" />
+       <listitem open="0" type="815" id="1066" />
+       <listitem open="0" type="815" id="1067" />
+       <listitem open="0" type="815" id="1069" />
+       <listitem open="0" type="815" id="1070" />
+       <listitem open="0" type="815" id="1071" />
+       <listitem open="0" type="815" id="1072" />
+       <listitem open="0" type="815" id="1073" />
+       <listitem open="0" type="815" id="1074" />
+       <listitem open="0" type="815" id="1075" />
+       <listitem open="0" type="815" id="1076" />
+       <listitem open="0" type="815" id="1077" />
+       <listitem open="0" type="815" id="1079" />
+       <listitem open="0" type="815" id="1080" />
+       <listitem open="0" type="815" id="1082" />
+       <listitem open="0" type="815" id="1068" />
+       <listitem open="0" type="815" id="1065" />
+       <listitem open="0" type="815" id="1078" />
+       <listitem open="0" type="815" id="1081" />
+      </listitem>
+     </listitem>
+     <listitem open="1" type="818" id="196" />
+     <listitem open="0" type="818" id="285" >
+      <listitem open="1" type="813" id="286" />
+      <listitem open="1" type="813" id="287" />
+      <listitem open="1" type="813" id="288" />
+      <listitem open="1" type="813" id="289" />
+      <listitem open="1" type="813" id="825" />
+      <listitem open="1" type="813" id="291" />
+     </listitem>
+     <listitem open="1" type="818" id="236" >
+      <listitem open="1" type="813" id="237" />
+      <listitem open="1" type="813" id="238" />
+      <listitem open="1" type="813" id="733" >
+       <listitem open="0" type="815" id="991" />
+       <listitem open="0" type="815" id="992" />
+       <listitem open="0" type="815" id="993" />
+       <listitem open="0" type="815" id="994" />
+       <listitem open="0" type="815" id="995" />
+       <listitem open="0" type="815" id="996" />
+       <listitem open="0" type="815" id="998" />
+       <listitem open="0" type="815" id="999" />
+       <listitem open="0" type="815" id="997" />
+       <listitem open="0" type="815" id="1000" />
+       <listitem open="0" type="815" id="1001" />
+      </listitem>
+     </listitem>
+     <listitem open="1" type="818" id="261" >
+      <listitem open="1" type="813" id="262" >
+       <listitem open="0" type="815" id="1226" />
+       <listitem open="0" type="815" id="1229" />
+       <listitem open="0" type="815" id="1223" />
+       <listitem open="0" type="815" id="1224" />
+       <listitem open="0" type="815" id="1227" />
+       <listitem open="0" type="815" id="1228" />
+       <listitem open="0" type="815" id="1231" />
+       <listitem open="0" type="815" id="1225" />
+       <listitem open="0" type="815" id="1230" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="818" id="292" >
+      <listitem open="1" type="813" id="293" />
+      <listitem open="1" type="813" id="294" />
+     </listitem>
+     <listitem open="0" type="818" id="295" >
+      <listitem open="1" type="813" id="296" />
+     </listitem>
+     <listitem open="1" type="818" id="297" />
+     <listitem open="1" type="818" id="239" >
+      <listitem open="1" type="813" id="240" />
+      <listitem open="1" type="813" id="241" />
+      <listitem open="1" type="813" id="242" >
+       <listitem open="0" type="815" id="1083" />
+       <listitem open="0" type="815" id="1084" />
+       <listitem open="0" type="815" id="1085" />
+       <listitem open="0" type="815" id="1086" />
+       <listitem open="0" type="815" id="1088" />
+       <listitem open="0" type="815" id="1089" />
+       <listitem open="0" type="815" id="1093" />
+       <listitem open="0" type="815" id="1092" />
+       <listitem open="0" type="815" id="1094" />
+       <listitem open="0" type="815" id="1095" />
+       <listitem open="0" type="815" id="1097" />
+       <listitem open="0" type="815" id="1098" />
+       <listitem open="0" type="815" id="1099" />
+       <listitem open="0" type="815" id="1101" />
+       <listitem open="0" type="815" id="1102" />
+       <listitem open="0" type="815" id="1103" />
+       <listitem open="0" type="815" id="1104" />
+       <listitem open="0" type="815" id="1105" />
+       <listitem open="0" type="815" id="1106" />
+       <listitem open="0" type="815" id="1107" />
+       <listitem open="0" type="815" id="1108" />
+       <listitem open="0" type="815" id="1109" />
+       <listitem open="0" type="815" id="1110" />
+       <listitem open="0" type="815" id="1112" />
+       <listitem open="0" type="815" id="1113" />
+       <listitem open="0" type="815" id="1114" />
+       <listitem open="0" type="815" id="1115" />
+       <listitem open="0" type="815" id="1116" />
+       <listitem open="0" type="815" id="1100" />
+       <listitem open="0" type="815" id="1087" />
+       <listitem open="0" type="815" id="1091" />
+       <listitem open="0" type="815" id="1090" />
+       <listitem open="0" type="815" id="1096" />
+       <listitem open="0" type="815" id="1111" />
+      </listitem>
+     </listitem>
+     <listitem open="0" type="818" id="298" >
+      <listitem open="1" type="813" id="299" />
+      <listitem open="1" type="813" id="300" />
+      <listitem open="1" type="813" id="301" />
+      <listitem open="1" type="813" id="302" />
+     </listitem>
+     <listitem open="0" type="818" id="303" >
+      <listitem open="1" type="813" id="304" />
+      <listitem open="1" type="813" id="305" />
+      <listitem open="1" type="813" id="306" />
+      <listitem open="1" type="813" id="307" />
+      <listitem open="1" type="813" id="309" />
+      <listitem open="1" type="813" id="308" />
+     </listitem>
+     <listitem open="1" type="818" id="310" />
+     <listitem open="0" type="818" id="311" >
+      <listitem open="1" type="813" id="313" />
+     </listitem>
+     <listitem open="0" type="818" id="312" >
+      <listitem open="1" type="813" id="314" />
+     </listitem>
+     <listitem open="0" type="830" id="-1" label="Datentypen" >
+      <listitem open="1" type="829" id="177" />
+      <listitem open="1" type="829" id="176" />
+      <listitem open="1" type="829" id="179" />
+      <listitem open="1" type="829" id="178" />
+      <listitem open="1" type="829" id="175" />
+      <listitem open="1" type="829" id="180" />
+      <listitem open="1" type="829" id="181" />
+     </listitem>
+    </listitem>
+    <listitem open="1" type="802" id="-1" label="Anwendungsfallansicht" />
+    <listitem open="1" type="821" id="-1" label="Komponentenansicht" />
+    <listitem open="1" type="827" id="-1" label="Verteilungsansicht" />
+   </listitem>
+  </listview>
+  <codegeneration/>
+ </XMI.extensions>
+</XMI>

Added: packages/thuban/branches/upstream/current/Doc/manual/Makefile
===================================================================
--- packages/thuban/branches/upstream/current/Doc/manual/Makefile	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/manual/Makefile	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,41 @@
+SRC_MAN=thuban-manual.xml
+SRC_MAN_DE=thuban-manual-de.xml
+SRC_IMAGES=$(wildcard images/*.png)
+EPS_IMAGES=$(patsubst %.png,%.eps,$(SRC_IMAGES))
+
+all: images man-all
+
+man-all: man-all-en man-all-de
+
+man-all-en: man-html man-dvi man-ps man-pdf man-rtf
+man-all-de: man-html-de man-dvi-de man-ps-de man-pdf-de man-rtf-de
+
+man-html:
+	db2html $(SRC_MAN)
+man-dvi: images
+	db2dvi $(SRC_MAN)
+man-ps: images
+	db2ps $(SRC_MAN)
+man-pdf: images
+	db2pdf $(SRC_MAN)
+man-rtf:
+	db2rtf $(SRC_MAN)
+
+man-html-de:
+	db2html $(SRC_MAN_DE)
+man-dvi-de: images
+	db2dvi $(SRC_MAN_DE)
+man-ps-de: images
+	db2ps $(SRC_MAN_DE)
+man-pdf-de: images
+	db2pdf $(SRC_MAN_DE)
+man-rtf-de:
+	db2rtf $(SRC_MAN_DE)
+
+images: $(EPS_IMAGES)
+
+%.eps: %.png
+	convert $< $@
+
+.PHONY: images
+

Added: packages/thuban/branches/upstream/current/Doc/manual/README
===================================================================
--- packages/thuban/branches/upstream/current/Doc/manual/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/manual/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,17 @@
+
+README for the Thuban Manual Sources
+====================================
+$Revision: 1367 $
+
+
+The manual is written using DocBook XML. To convert to other formats use
+the docbook tools. Examples:
+
+Convert to PostScript (the output will be manual.ps)
+
+ $ db2ps manual.xml
+
+to HTML (the output will be in a subdirectory manual/)
+
+ $ db2html manual.xml
+

Added: packages/thuban/branches/upstream/current/Doc/manual/images/1_2_legend_close.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/1_2_legend_close.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/1_2_legend_dock.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/1_2_legend_dock.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.ps
===================================================================
--- packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.ps	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.ps	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,12899 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%For: Jonathan Coles,,,
+%%CreationDate: Fri 18 Jul 2003 02:24:54 PM CEST
+%%Title: 1_2_mainwindow.ps
+%%Creator: Sketch 0.6.14
+%%Pages: 1
+%%BoundingBox: 16 31 519 370
+%%Extensions: CMYK
+%%DocumentSuppliedResources: (atend)
+%%DocumentNeededResources: font Helvetica-Bold
+%%EndComments
+
+%%BeginProlog
+%%BeginResource: procset Linux-Sketch-Procset 1.0 2
+/SketchDict 100 dict def
+SketchDict begin
+/bd { bind def } bind def
+/x { exch } bd
+/xd { exch def } bd
+/PI 3.14159265358979323846264338327 def
+/radgrad { 180 mul PI div } bd
+/skstartmatrix matrix currentmatrix def
+/tmpmat matrix def
+/ISOLatin1Encoding dup where
+{ pop pop }
+{  [/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand
+/quoteright /parenleft /parenright /asterisk /plus /comma /minus /period
+/slash /zero /one /two /three /four /five /six /seven /eight /nine /colon
+/semicolon /less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J
+/K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash
+/bracketright /asciicircum /underscore /quoteleft /a /b /c /d /e /f /g /h /i
+/j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright
+/asciitilde /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
+/.notdef /.notdef /dotlessi /grave /acute /circumflex /tilde /macron /breve
+/dotaccent /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek
+/caron /space /exclamdown /cent /sterling /currency /yen /brokenbar /section
+/dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen
+/registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu
+/paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright
+/onequarter /onehalf /threequarters /questiondown /Agrave /Aacute /Acircumflex
+/Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex
+/Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve
+/Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute
+/Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute
+/acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute
+/ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde
+/ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave
+/uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] def
+}
+ifelse
+/arct dup where
+{pop pop}
+{
+/arct {arcto pop pop pop pop} bd
+}
+ifelse
+/size 0 def
+/fontname 0 def
+/newfont 0 def
+/sf {
+/size xd
+/fontname xd
+fontname findfont
+dup /Encoding get StandardEncoding eq
+{
+dup
+length dict /newfont xd
+{
+1 index
+/FID ne
+{ newfont 3 1 roll put }
+{ pop pop }
+ifelse
+} forall
+newfont /Encoding ISOLatin1Encoding put
+fontname newfont definefont
+}
+if
+size scalefont setfont
+} bd
+/pusht {matrix currentmatrix} bd
+/popt {setmatrix} bd
+/pushc {gsave} bd
+/popc {grestore} bd
+/rgb {setrgbcolor} bd
+/w { setlinewidth } bd
+/j { setlinejoin } bd
+/J { setlinecap } bd
+/d { setdash } bd
+/F { eofill } bd
+/f { closepath F } bd
+/S {
+pusht
+skstartmatrix setmatrix stroke 
+popt
+} bd
+/s { closepath S } bd
+/m { moveto } bd
+/l { lineto } bd
+/c { curveto } bd
+/txt {
+/tmpmat tmpmat currentmatrix def
+dup type /arraytype eq {concat} {translate} ifelse
+0 0 m
+tmpmat
+} bd
+/T {txt x show popt} bd
+/P {txt x true charpath popt} bd
+/TP {txt x dup show 0 0 m true charpath popt} bd
+/C {newpath 0 360 arc} bd
+/R {
+2 copy m
+x 2 index l
+x 2 index x l
+l
+closepath
+} bd
+/ellipse { 
+dup type /arraytype eq
+{
+pusht x concat
+0 0 1.0 C 
+popt
+}	
+{
+pusht 5 1 roll
+4 -1 roll concat
+newpath
+dup 2 eq {
+0 0 m 
+} if 
+3 1 roll
+radgrad x
+radgrad x
+0 0 1   5 -2 roll
+arc
+0 ne { closepath } if
+popt
+}
+ifelse
+} bd
+/radius1 0 def
+/radius2 0 def
+/factor 0 def
+/rect {
+dup type /arraytype eq
+{
+pusht x concat
+0 0 m  1 0 l  1 1 l  0 1 l  closepath
+popt
+}
+{
+/radius2 xd
+/radius1 xd
+pusht x concat
+radius1 radius2 div  1  scale
+0 radius2 m
+0 1  radius2 1  radius2  arct
+radius2 radius1 div
+dup 1  1 index 0  radius2  arct
+0  0 0  radius2  arct
+0 0  0 1  radius2 arct
+closepath
+popt
+}
+ifelse
+} bd
+/buf 0 def
+/width 0 def
+/height 0 def
+/skcimg {
+/tmpmat tmpmat currentmatrix def
+{ concat } if
+/height xd
+/width xd
+/buf width 3 mul string def
+width height scale
+width height 8
+[width	 0   0	 height neg	  0  height]
+{ currentfile buf readhexstring pop } bind
+false 3 colorimage
+tmpmat setmatrix
+} bd
+/skgimg {
+/tmpmat tmpmat currentmatrix def
+{ concat } if
+/height xd
+/width xd
+/buf width string def
+width height scale
+width height 8
+[width	 0   0	 height neg	  0  height]
+{ currentfile buf readhexstring pop } bind
+image
+tmpmat setmatrix
+} bd
+/rclip {
+4 2 roll m
+dup 0 x rlineto
+x 0 rlineto
+neg 0 x rlineto
+closepath
+clip
+} bd
+/skeps {
+10 dict begin
+/sk_state save def
+concat
+3 index neg 3 index neg translate
+rclip
+0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin
+10 setmiterlimit [ ] 0 setdash
+newpath
+/sk_dict_count countdictstack def
+/sk_count count 1 sub def
+userdict begin
+/showpage { } def
+/languagelevel where
+{
+pop
+languagelevel 1 ne
+{
+false setstrokeadjust
+false setoverprint
+} if
+} if
+} bd 
+/skepsend {
+count sk_count sub { pop } repeat
+countdictstack sk_dict_count sub { end } repeat
+sk_state restore
+end
+} bd
+/gradidx 0 def
+/gradient { 
+3 mul array
+/gradidx 0 def
+} bd
+/$ {
+3 index gradidx       5 -1 roll put 
+2 index gradidx 1 add 4 -1 roll put 
+1 index gradidx 2 add 3 -1 roll put 
+/gradidx gradidx 3 add def
+} bd
+/! { 
+3 
+{
+dup dup gradidx dup 3 1 roll 3 sub get put
+/gradidx gradidx 1 add def
+}
+repeat
+} bd
+/gradcolor {
+3 mul dup 2 add 1 exch	% idx  1  idx+2
+{
+1 index exch	% array array i
+get		% array component
+exch		% component array
+}
+for
+4 1 roll
+} bd
+/x0 0 def /y0 0 def /x1 0 def /y1 0 def
+/left 0 def /right 0 def /top 0 def /bottom 0 def
+/numcolors 0 def
+/axial	{
+/y1 xd /x1 xd /y0 xd /x0 xd
+dup length 3 idiv /numcolors xd
+pusht exch  % ctm array
+x0 x1 ne y0 y1 ne or
+{
+x0 y0 translate
+[x1 x0 sub  y1 y0 sub	dup neg    2 index    0	    0] concat
+clippath flattenpath pathbbox
+/top xd /right xd /bottom xd /left xd
+newpath
+0 gradcolor rgb clippath f
+0 1 numcolors 1 sub
+{
+dup numcolors div
+3 1 roll
+gradcolor rgb
+exch
+bottom right top R f
+}
+for
+}
+if 
+pop
+popt
+} bd
+/r0 0 def /r1 0 def /dr 0 def
+/radial	{
+/r1 xd /r0 xd /y0 xd /x0 xd
+/dr r1 r0 sub def
+dup length 3 idiv /numcolors xd
+pusht exch  % ctm array
+r0 r1 ne
+{
+x0 y0 translate
+clippath flattenpath pathbbox
+/top xd /right xd /bottom xd /left xd
+newpath
+dr 0 gt {numcolors 1 sub}{0} ifelse gradcolor rgb
+clippath f
+dr 0 gt {numcolors 1 sub -1 0} { 0 1 numcolors 1 sub} ifelse
+{
+dup numcolors div dr mul r0 add
+3 1 roll
+gradcolor rgb
+exch
+0 0 3 -1 roll C f
+}
+for
+}
+if 
+pop
+popt
+} bd
+/max {
+2 copy lt {exch} if pop
+} bd
+/conical {
+pusht 5 1 roll
+3 1 roll /y0 xd /x0 xd
+x0 y0 translate
+radgrad rotate
+dup length 3 idiv /numcolors xd
+clippath flattenpath pathbbox newpath
+4 { abs 4 1 roll} repeat
+3 { max } repeat
+2 mul
+dup scale
+0 gradcolor rgb
+0 0 1 0 360 arc f
+1 1 numcolors 1 sub
+{
+dup numcolors div 180 mul
+3 1 roll
+gradcolor rgb
+exch
+0 0 moveto
+0 0 1  4 -1 roll  dup neg  arc
+closepath f
+}
+for
+pop
+popt
+} bd
+/XStep 0 def /YStep 0 def /imagedata 0 def /components 0 def
+/tileimage2 {
+exch 4 2 roll
+/height xd
+/width xd
+mark
+/components 2 index
+/PatternType 1
+/PaintType 1
+/TilingType 1
+/BBox [0 0 width height]
+/XStep width
+/YStep height
+/PaintProc {
+begin
+XStep YStep 8
+matrix
+imagedata
+false
+components
+colorimage
+end
+}
+counttomark 2 div cvi dup dict begin
+{ def } repeat
+pop currentdict end
+dup
+/imagedata
+4 -1 roll
+width height mul mul string
+currentfile exch readhexstring pop
+put
+exch
+makepattern
+setpattern
+clippath
+eofill
+} bd
+/tileimage1 {
+concat
+/components xd
+/height xd
+/width xd
+/imagedata
+currentfile
+width height mul components mul string
+readhexstring pop
+def
+clippath flattenpath pathbbox
+/top xd /right xd /bottom xd /left xd
+left width div floor width mul
+bottom height div floor height mul
+translate
+top bottom sub height div ceiling cvi
+{
+gsave
+right left sub width div ceiling cvi
+{
+width height 8 matrix
+components 1 eq
+{
+{ imagedata }
+image
+}
+{
+imagedata
+false components
+colorimage
+}
+ifelse
+width 0 translate
+}
+repeat
+grestore
+0 height translate
+}
+repeat
+} bd
+/makepattern where
+{
+pop
+/tileimage /tileimage2 load def
+}
+{
+/tileimage /tileimage1 load def
+}
+ifelse
+end
+%%EndResource
+%%EndProlog
+
+%%BeginSetup
+%%IncludeResource: font Helvetica-Bold
+
+10.433 setmiterlimit
+%%EndSetup
+
+%%Page: 1 1
+SketchDict begin
+497 332 [1 0 0 1 19.6378 35.9449] true
+%%BeginData: 12377 Hex Lines
+skcimg
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84424142D6D2CEFFFFFFD6D2CED6D2CE848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848486848482848486848482
+848486848482848486848482848C868C8482848486848486848C868C8482848C868C8486848C868C
+8486848C868C8486848C868C8486848C868C8486848C8A8C8486848C868C8486848C8A8C8486848C
+8A8C8486848C8A8C8486848C8A8C8C868C8C8A8C8486848C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A
+8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C8C8E8C
+8C8A8C8C8E8C8C8A8C948E948C8A8C8C8E8C8C8E8C948E948C8A8C948E948C8E8C948E948C8E8C94
+8E948C8E8C948E948C8E8C948E948C8E8C9492948C8E8C948E948C8E8C9492948C8E8C9492948C8E
+8C9492948C8E8C949294948E949492948C8E8C949294949294949294949294949294949294949294
+94929494929494929494929494929494929494929494969494929494969494929494969494929494
+96949492949C969C9492949496949496949C969C9492949C969C9496949C969C9496949C969C9496
+949C969C9496949C969C9496949C9A9C9496949C969C9496949C9A9C9496949C9A9C9496949C9A9C
+9496949C9A9C9C969C9C9A9C9496949C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C
+9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A
+9CA59EA59C9A9C9C9E9C9C9E9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA5
+9C9E9CA59EA59C9E9CA5A2A59C9E9CA59EA59C9E9CA5A2A59C9E9CA5A2A59C9E9CA5A2A59C9E9CA5
+A2A5A59EA5A5A2A59C9E9CA5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2
+A5A5A2A5A5A2A5A5A2A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5ADA6AD
+A5A2A5A5A6A5A5A6A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5AD
+A6ADA5A6A5ADAAADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADADA6
+ADADAAADA5A6A5ADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAAD
+ADAAADADAAADADAAADADAEADADAAADADAEADADAAADADAEADADAAADADAEADADAAADB5AEB5ADAAADAD
+AEADADAEADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAE
+ADB5B2B5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5
+ADAEADB5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5
+B2B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5BDB6BDB5B2B5B5B6B5B5B6
+B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABD
+B5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BD
+BABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBA
+BDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDC5BEC5BDBABDBDBEBDBDBEBDC5BEC5
+BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5
+BEC5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5C2
+C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5
+C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5
+C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2
+C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5
+C5C2C5D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE84828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+848482848482848482848482848486848482848482848482848C868C8482848486848482848C868C
+8482848C868C8482848C868C8486848C868C8482848C868C8486848C868C8486848C868C8486848C
+868C8486848C868C8486848C868C8486848C8A8C8C868C8C8A8C8486848C8A8C8C868C8C8A8C8486
+848C8A8C8C868C8C8A8C8C868C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C
+8C8A8C8C8A8C8C8A8C8C8E8C8C8A8C8C8A8C8C8A8C948E948C8A8C8C8E8C8C8A8C948E948C8A8C94
+8E948C8A8C948E948C8E8C948E948C8A8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E
+8C948E948C8E8C948E948C8E8C949294948E949492948C8E8C949294948E949492948C8E8C949294
+948E94949294948E9494929494929494929494929494929494929494929494929494929494929494
+92949492949496949492949492949492949C969C9492949496949492949C969C9492949C969C9492
+949C969C9496949C969C9492949C969C9496949C969C9496949C969C9496949C969C9496949C969C
+9496949C969C9496949C9A9C9C969C9C9A9C9496949C9A9C9C969C9C9A9C9496949C9A9C9C969C9C
+9A9C9C969C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A
+9C9C9E9C9C9A9C9C9A9C9C9A9CA59EA59C9A9C9C9E9C9C9A9CA59EA59C9A9CA59EA59C9A9CA59EA5
+9C9E9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5
+9EA59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A59EA5A5A2A5A59E
+A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A6A5
+A5A2A5A5A2A5A5A2A5ADA6ADA5A2A5A5A6A5A5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A6A5AD
+A6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6
+A5ADAAADA5A6A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADA6ADADAAADADA6ADADAAAD
+ADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAEADADAAADAD
+AAADADAAADB5AEB5ADAAADADAEADADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAA
+ADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5B2B5
+ADAEADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5AEB5B5B2B5B5AEB5B5B2B5B5B2B5B5
+B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2
+B5BDB6BDB5B2B5B5B6B5B5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BD
+B5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BD
+BABDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDB6BDBDBABDBDB6BDBDBABDBDBABDBDBABDBDBA
+BDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDC5BEC5
+BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBEBDC5
+BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5C2C5BDBE
+BDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5BEC5C5C2C5C5BEC5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5
+C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5
+C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2
+C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5
+C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5
+C2C5C5C2C5C5C2C5C5C2C5C5C2C5D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE8482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848486848482848486848482848486848482848486848482848C868C8482848486848486
+848C868C8482848C868C8486848C868C8486848C868C8486848C868C8486848C868C8486848C8A8C
+8486848C868C8486848C8A8C8486848C8A8C8486848C8A8C8486848C8A8C8C868C8C8A8C8486848C
+8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A
+8C8C8E8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C948E948C8A8C8C8E8C8C8E8C948E94
+8C8A8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C9492948C8E8C94
+8E948C8E8C9492948C8E8C9492948C8E8C9492948C8E8C949294948E949492948C8E8C9492949492
+94949294949294949294949294949294949294949294949294949294949294949294949294949694
+9492949496949492949496949492949496949492949C969C9492949496949496949C969C9492949C
+969C9496949C969C9496949C969C9496949C969C9496949C969C9496949C9A9C9496949C969C9496
+949C9A9C9496949C9A9C9496949C9A9C9496949C9A9C9C969C9C9A9C9496949C9A9C9C9A9C9C9A9C
+9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9E9C9C9A9C9C
+9E9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9CA59EA59C9A9C9C9E9C9C9E9CA59EA59C9A9CA59EA59C9E
+9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A59C9E9CA59EA59C9E9CA5A2A5
+9C9E9CA5A2A59C9E9CA5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A5A2A5A5A2A5A5A2A5A5
+A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2
+A5A5A6A5A5A2A5A5A6A5A5A2A5ADA6ADA5A2A5A5A6A5A5A6A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6AD
+A5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5AD
+AAADA5A6A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADAAADADAAADADAAADADAAADADAA
+ADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAEADADAAADADAEADADAAADADAEAD
+ADAAADADAEADADAAADB5AEB5ADAAADADAEADADAEADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5
+AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5B2B5ADAE
+ADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5
+B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5
+B6B5B5B2B5BDB6BDB5B2B5B5B6B5B5B6B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6
+B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABD
+B5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBD
+BABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBA
+BDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5
+BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5
+C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFF424142C5C2C5C5C2C5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142C5C2C5C5C2C5D6D2CED6D2CE848284424142D6D2CE
+FFFFFFD6D2CED6D2CE84828484828484828484828484828484828484828484828484828484828484
+82840000000000000000000000008482848482848482848482848482848486848482848482848482
+848C868C8482848486848482848C868C8482848C868C8482848C868C8486848C868C8482848C868C
+8486848C868C8486848C868C8486848C868C8486848C868C8486848C868C8486848C8A8C8C868C8C
+8A8C8486848C8A8C8C868C8C8A8C8C868C8C8A8C8C868C8C8A8C8C868C8C8A8C8C8A8C8C8A8C8C8A
+8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8E8C8C8A8C8C8A8C8C8A8C948E94
+8C8A8C8C8E8C8C8A8C948E948C8A8C948E948C8A8C948E948C8E8C948E948C8A8C948E948C8E8C94
+8E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C949294948E949492948C8E
+8C949294948E94949294948E94949294948E94949294948E94949294949294949294949294949294
+9492949492949492949492949492949492949492949496949492949492949492949C969C94929494
+96949492949C969C9492949C969C9492949C969C9496949C969C9492949C969C9496949C969C9496
+949C969C9496949C969C9496949C969C9496949C969C9496949C9A9C9C969C9C9A9C9496949C9A9C
+9C969C9C9A9C9C969C9C9A9C9C969C9C9A9C9C969C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C
+9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9CA59EA59C9A9C9C9E9C9C9A
+9CA59EA59C9A9CA59EA59C9A9CA59EA59C9A9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E9CA59EA5
+9C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A59EA5A5
+A2A5A59EA5A5A2A5A59EA5A5A2A5A59EA5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2
+A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5ADA6ADA5A2A5A5A6A5A5A2A5ADA6AD
+A5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5AD
+A6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADA6ADADAAADADA6
+ADADAAADADA6ADADAAADADA6ADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAAD
+ADAAADADAAADADAAADADAAADADAAADADAAADADAAADB5AEB5ADAAADADAEADADAAADB5AEB5ADAAADB5
+AEB5ADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAE
+ADB5AEB5ADAEADB5AEB5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5AEB5B5B2B5B5AEB5B5B2B5
+B5AEB5B5B2B5B5AEB5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5
+B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5BDB6BDB5B2B5B5B6B5B5B2B5BDB6BDB5B2B5BDB6BDB5B2
+B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BD
+B5B6B5BDB6BDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDB6BDBDBABDBDB6BDBDBABDBDB6BDBD
+BABDBDB6BDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBA
+BDBDBABDBDBABDBDBABDBDBABDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5
+BDBABDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5
+BEC5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5BEC5C5C2C5C5BEC5C5C2C5C5BEC5C5C2C5C5BE
+C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5
+FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE848284424142C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142C5C2C5C5C2C5D6D2CED6
+D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE8482848482840000008482848482848482848482
+84848284848284848284000000000000000000000000000000000000000000848284848284848284
+848284848284848284848284848284848284848284D6D2CED6D2CE84828484828484868484828484
+86848482848486848482848486848482848C868C848284D6D2CED6D2CE8C868C8482848C868C8486
+848C868C8486848C868C8486848C868C8486848C868C8486848C8A8C8486848C868C8486848C8A8C
+8486848C8A8C8486848C8A8C8486848C8A8C8C868C8C8A8C8486848C8A8C8C8A8C8C8A8C8C8A8C8C
+8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A
+8C8C8E8C8C8A8C8C8E8C8C8A8CD6D2CED6D2CE8C8E8C8C8E8C948E948C8A8C948E948C8E8C948E94
+8C8E8C948E948C8E8C948E948C8E8C948E948C8E8C9492948C8E8C948E948C8E8C949294D6D2CED6
+D2CE8C8E8C9492948C8E8C949294948E949492948C8E8C9492949492949492949492949492949492
+94949294949294949294949294949294949294949294949294949694949294949694949294949694
+9492949496949492949C969C9492949496949496949C969C9492949C969C9496949C969C9496949C
+969C9496949C969C9496949C969C9496949C9A9C9496949C969C9496949C9A9C9496949C9A9C9496
+949C9A9C9496949C9A9C9C969C9C9A9C9496949C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C
+9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9C9C
+9E9C9C9A9CA59EA59C9A9C9C9E9C9C9E9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E
+9CA59EA59C9E9CA59EA59C9E9CA5A2A59C9E9CA59EA59C9E9CA5A2A59C9E9CA5A2A59C9E9CA5A2A5
+9C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5
+A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2
+A5ADA6ADA5A2A5A5A6A5A5A6A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6AD
+A5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADA5A6A5AD
+AAADADA6ADADAAADA5A6A5ADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAA
+ADADAAADADAAADADAAADADAAADADAEADADAAADADAEADADAAADADAEADADAAADADAEADADAAADB5AEB5
+ADAAADADAEADADAEADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5
+AEB5ADAEADB5B2B5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5B5AE
+B5B5B2B5ADAEADB5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5
+B5B2B5B5B2B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5BDB6BDB5B2B5B5
+B6B5B5B6B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6
+B5BDBABDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABDBDB6BDBDBABD
+B5B6B5BDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBD
+BABDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDC5BEC5BDBABDBDBEBDBDBE
+BDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5
+BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5
+C2C5C5C2C5C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE000000000000000000000000
+000000000000000000000000000000D6D2CED6D2CE848284424142C5C2C5C5C2C5FFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42C5C2C5C5C2C5D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284848284848284
+000000848284000000000000848284000000848284000000FF0000FF000000000000FF0000FF0000
+0000848284848284848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8C868CD6D2CED6D2CE8482
+848C868C8482848C868C8482848C868C8486848C868C8482848C868C8486848C868CD6D2CED6D2CE
+8486848C868C8486848C868C8486848C868C8486848C8A8C8C868C8C8A8C8486848C8A8C8C868C8C
+8A8C8486848C8A8C8C868C8C8A8C8C868C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A
+8C8C8A8C8C8A8C8C8A8CD6D2CED6D2CED6D2CED6D2CE8C8A8C948E948C8A8C8C8E8C8C8A8C948E94
+8C8A8C948E948C8A8C948E948C8E8C948E948C8A8C948E94D6D2CED6D2CE8C8E8C948E948C8E8C94
+8E948C8E8C948E948C8E8C948E948C8E8C949294948E949492948C8E8C949294948E949492948C8E
+8C949294948E94D6D2CED6D2CE949294949294949294949294949294949294949294949294949294
+9492949492949492949496949492949492949492949C969C9492949496949492949C969C9492949C
+969C9492949C969C9496949C969C9492949C969C9496949C969C9496949C969C9496949C969C9496
+949C969C9496949C969C9496949C9A9C9C969C9C9A9C9496949C9A9C9C969C9C9A9C9496949C9A9C
+9C969C9C9A9C9C969C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C
+9A9C9C9A9C9C9E9C9C9A9C9C9A9C9C9A9CA59EA59C9A9C9C9E9C9C9A9CA59EA59C9A9CA59EA59C9A
+9CA59EA59C9E9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA5
+9C9E9CA59EA59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A59EA5A5
+A2A5A59EA5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2
+A5A5A6A5A5A2A5A5A2A5A5A2A5ADA6ADA5A2A5A5A6A5A5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6AD
+A5A6A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5AD
+A6ADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADA6ADADAAADADA6
+ADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAEAD
+ADAAADADAAADADAAADB5AEB5ADAAADADAEADADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAEADB5
+AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAE
+ADB5B2B5ADAEADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5AEB5B5B2B5B5AEB5B5B2B5
+B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5
+B2B5B5B2B5BDB6BDB5B2B5B5B6B5B5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B2
+B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABD
+B5B6B5BDBABDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDB6BDBDBABDBDB6BDBDBABDBDBABDBD
+BABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBA
+BDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5
+BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5
+C2C5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5BEC5C5C2C5C5BEC5C5C2C5C5C2C5C5C2C5C5C2
+C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE00
+0000000000000000000000000000000000000000000000000000D6D2CED6D2CE848284424142C5C2
+C5C5C2C5FFFFFFD6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6D2CE000000000000
+D6D2CED6D2CE848284424142C5C2C5C5C2C5D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6
+D2CE848284848284FF0000848284848284848284000000848284848284848284000000FF0000FF00
+0000000000FF0000FF00000000848284848284848284848284848284D6D2CED6D2CE848284848284
+848284D6D2CED6D2CE8486848482848486848482848486848482848486848482848C868C84828484
+8684848684D6D2CED6D2CE8C868C8486848C868C8486848C868C8486848C868C8486848C868C8486
+848C8A8C8486848C868C8486848C8A8C8486848C8A8C8486848C8A8C8486848C8A8C8C868C8C8A8C
+8486848C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8CD6D2CED6D2CE8C8A8C8C8A8C8C8A8C8C
+8A8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C948E948C8A8CD6D2CED6D2
+CE948E948C8A8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C949294
+8C8E8C948E948C8E8C9492948C8E8C949294D6D2CED6D2CE8C8E8C949294948E949492948C8E8C94
+92949492949492949492949492949492949492949492949492949492949492949492949492949492
+949496949492949496949492949496949492949496949492949C969C9492949496949496949C969C
+9492949C969C9496949C969C9496949C969C9496949C969C9496949C969C9496949C9A9C9496949C
+969C9496949C9A9C9496949C9A9C9496949C9A9C9496949C9A9C9C969C9C9A9C9496949C9A9C9C9A
+9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9E9C
+9C9A9C9C9E9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9CA59EA59C9A9C9C9E9C9C9E9CA59EA59C9A9CA5
+9EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A59C9E9CA59EA59C9E
+9CA5A2A59C9E9CA5A2A59C9E9CA5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A5A2A5A5A2A5
+A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A6A5A5A2A5A5
+A6A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5ADA6ADA5A2A5A5A6A5A5A6A5ADA6ADA5A2A5ADA6ADA5A6
+A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADA6ADA5A6A5ADAAAD
+A5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADAAADADAAADADAAADAD
+AAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAEADADAAADADAEADADAA
+ADADAEADADAAADADAEADADAAADB5AEB5ADAAADADAEADADAEADB5AEB5ADAAADB5AEB5ADAEADB5AEB5
+ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5
+B2B5ADAEADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2
+B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5
+B5B2B5B5B6B5B5B2B5BDB6BDB5B2B5B5B6B5B5B6B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BD
+B6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDBABDB5B6
+B5BDBABDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABD
+BDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDBD
+BEBDBDBABDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBE
+BDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5
+BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5FFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CE
+D6D2CE848284424142C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6
+D2CE000000000000D6D2CED6D2CED6D2CE848284424142C5C2C5C5C2C5D6D2CED6D2CE8482844241
+42D6D2CEFFFFFFD6D2CED6D2CE848284848284848284FF0000848284FF0000FF0000848284FF0000
+84828400000084000000000000000000000000FF00000000848284848284848284848684848284D6
+D2CED6D2CE8C868C848284848684D6D2CED6D2CED6D2CED6D2CED6D2CE8C868C848684D6D2CED6D2
+CE8C868C848684D6D2CED6D2CE8C868CD6D2CED6D2CED6D2CED6D2CED6D2CE8C868C8486848C8A8C
+D6D2CED6D2CED6D2CED6D2CE8C868C8C8A8CD6D2CED6D2CED6D2CED6D2CED6D2CE8C8A8C8C8A8C8C
+8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8E8C8C8A8CD6D2CED6D2
+CE948E948C8A8C8C8E8CD6D2CED6D2CED6D2CED6D2CE8C8A8C948E94D6D2CED6D2CED6D2CED6D2CE
+8C8E8C948E94D6D2CED6D2CE8C8E8C948E94D6D2CED6D2CED6D2CED6D2CE8C8E8C949294D6D2CED6
+D2CED6D2CED6D2CED6D2CE949294948E94949294D6D2CED6D2CED6D2CED6D2CED6D2CE9492949492
+94949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE949294D6D2CED6D2CED6D2CE9492949C969C
+949294D6D2CED6D2CED6D2CED6D2CE9C969C949294D6D2CED6D2CED6D2CED6D2CED6D2CE9496949C
+969C9496949C969C9496949C969C9496949C969C9496949C969C9496949C9A9C9C969C9C9A9C9496
+949C9A9C9C969C9C9A9C9C969C9C9A9C9C969C9C9A9C9C969C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C
+9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9CA59EA59C9A9C9C
+9E9C9C9A9CA59EA59C9A9CA59EA59C9A9CA59EA59C9A9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E
+9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5
+A59EA5A5A2A5A59EA5A5A2A5A59EA5A5A2A5A59EA5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5
+A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5ADA6ADA5A2A5A5A6A5A5A2
+A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6AD
+A5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADA6ADAD
+AAADADA6ADADAAADADA6ADADAAADADA6ADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAA
+ADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADB5AEB5ADAAADADAEADADAAADB5AEB5
+ADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5
+AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5AEB5B5B2B5B5AE
+B5B5B2B5B5AEB5B5B2B5B5AEB5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5
+B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5BDB6BDB5B2B5B5B6B5B5B2B5BDB6BDB5B2B5BD
+B6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6
+B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDB6BDBDBABDBDB6BDBDBABD
+BDB6BDBDBABDBDB6BDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBD
+BABDBDBABDBDBABDBDBABDBDBABDBDBABDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBA
+BDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5
+BDBEBDC5BEC5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5BEC5C5C2C5C5BEC5C5C2C5C5BEC5C5
+C2C5C5BEC5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2
+C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE000000D6D2CED6D2CE848284424142C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CE000000000000000000000000D6D2CED6D2CED6D2CED6D2CE848284424142C5C2C5C5C2C5
+D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE84828484828400000084828484828484
+8284FF00008482848482848482840000000000000000000000000000000000000000008482848482
+84848284848284848284D6D2CED6D2CE848284848284848284D6D2CED6D2CE848284848284D6D2CE
+D6D2CE848684D6D2CED6D2CE848284848684D6D2CED6D2CE848284D6D2CED6D2CE8C868C848284D6
+D2CED6D2CE8C868C8486848C868C8486848C868CD6D2CED6D2CE848684D6D2CED6D2CE8C868C8486
+84D6D2CED6D2CE8C8A8C8486848C8A8C8486848C8A8C8C868C8C8A8C8486848C8A8C8C8A8C8C8A8C
+8C8A8C8C8A8CD6D2CED6D2CE8C8A8C8C8A8CD6D2CED6D2CE8C8A8C8C8A8C8C8A8C8C8E8CD6D2CED6
+D2CE8C8A8C8C8E8CD6D2CED6D2CE8C8A8CD6D2CED6D2CE8C8E8C8C8E8C948E948C8A8C948E94D6D2
+CED6D2CE8C8E8CD6D2CED6D2CE948E948C8E8CD6D2CED6D2CE949294D6D2CED6D2CE8C8E8C949294
+D6D2CED6D2CE8C8E8C9492948C8E8C949294D6D2CED6D2CE8C8E8C949294D6D2CED6D2CE94929494
+9294D6D2CED6D2CE949294949294949294949294949294D6D2CED6D2CE949694D6D2CED6D2CE9492
+94949694D6D2CED6D2CE9492949C969C9492949496949496949C969C9492949C969C9496949C969C
+9496949C969C9496949C969C9496949C969C9496949C9A9C9496949C969C9496949C9A9C9496949C
+9A9C9496949C9A9C9496949C9A9C9C969C9C9A9C9496949C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A
+9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9C9C9E9C
+9C9A9C9C9E9C9C9A9CA59EA59C9A9C9C9E9C9C9E9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E9CA5
+9EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A59C9E9CA59EA59C9E9CA5A2A59C9E9CA5A2A59C9E
+9CA5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5
+A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5A5
+A6A5A5A2A5ADA6ADA5A2A5A5A6A5A5A6A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6
+A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAAD
+A5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADAD
+AAADADAAADADAAADADAAADADAAADADAAADADAEADADAAADADAEADADAAADADAEADADAAADADAEADADAA
+ADB5AEB5ADAAADADAEADADAEADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5
+ADAEADB5AEB5ADAEADB5B2B5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5
+B2B5B5AEB5B5B2B5ADAEADB5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2
+B5B5B2B5B5B2B5B5B2B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5BDB6BD
+B5B2B5B5B6B5B5B6B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BD
+B6BDB5B6B5BDBABDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABDBDB6
+BDBDBABDB5B6B5BDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABD
+BDBABDBDBABDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDC5BEC5BDBABDBD
+BEBDBDBEBDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBE
+BDC5C2C5BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5C5BEC5C5C2C5
+BDBEBDC5C2C5C5C2C5C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE000000D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE848284424142C5C2C5C5C2C5FFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284424142C5C2C5C5C2C5D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE8482848482
+848482840000008482840000000000008482840000008482840000000000FF0000FF000000FFFF00
+FFFF00000000848284848284848284848284848284D6D2CED6D2CE8482848482848C868CD6D2CED6
+D2CE8482848C868CD6D2CED6D2CE848284D6D2CED6D2CE8C868C848284D6D2CED6D2CE8C868CD6D2
+CED6D2CE8486848C868CD6D2CED6D2CE8486848C868CD6D2CED6D2CED6D2CED6D2CED6D2CE8C8A8C
+D6D2CED6D2CE8486848C8A8CD6D2CED6D2CE8C868C8C8A8C8C8A8C8C8A8CD6D2CED6D2CED6D2CED6
+D2CE8C8A8C8C8A8C8C8A8C8C8A8C8C8A8CD6D2CED6D2CE8C8A8C8C8A8CD6D2CED6D2CE8C8E8C8C8A
+8C948E948C8A8CD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE948E94D6D2CED6D2CE8C8E8C948E94
+D6D2CED6D2CED6D2CED6D2CED6D2CE948E94D6D2CED6D2CE948E94949294D6D2CED6D2CE948E94D6
+D2CED6D2CE949294948E94D6D2CED6D2CE949294949294949294949294D6D2CED6D2CE9492949492
+94D6D2CED6D2CE949294949294D6D2CED6D2CE949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE
+949294D6D2CED6D2CE9C969C949694D6D2CED6D2CE9C969C9496949C969C9496949C969C9496949C
+969C9496949C969C9496949C969C9496949C9A9C9C969C9C9A9C9496949C9A9C9C969C9C9A9C9496
+949C9A9C9C969C9C9A9C9C969C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C
+9C9A9C9C9A9C9C9A9C9C9E9C9C9A9C9C9A9C9C9A9CA59EA59C9A9C9C9E9C9C9A9CA59EA59C9A9CA5
+9EA59C9A9CA59EA59C9E9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E
+9CA59EA59C9E9CA59EA59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5
+A59EA5A5A2A5A59EA5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5
+A2A5A5A2A5A5A6A5A5A2A5A5A2A5A5A2A5ADA6ADA5A2A5A5A6A5A5A2A5ADA6ADA5A2A5ADA6ADA5A2
+A5ADA6ADA5A6A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6AD
+A5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADA6ADAD
+AAADADA6ADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAA
+ADADAEADADAAADADAAADADAAADB5AEB5ADAAADADAEADADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5
+ADAEADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5
+AEB5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5AEB5B5B2B5B5AE
+B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5
+B5B2B5B5B2B5B5B2B5BDB6BDB5B2B5B5B6B5B5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BD
+B6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6
+B5BDBABDB5B6B5BDBABDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDB6BDBDBABDBDB6BDBDBABD
+BDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBD
+BABDBDBABDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBA
+BDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5
+BDBEBDC5C2C5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5BEC5C5C2C5C5BEC5C5C2C5C5C2C5C5
+C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE84828442
+4142C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000D6D2
+CED6D2CED6D2CED6D2CE848284424142C5C2C5C5C2C5D6D2CED6D2CE848284424142D6D2CEFFFFFF
+D6D2CED6D2CE8482848482840000FF84828484828484828400000084828484828484828400000000
+00FF0000FF000000FFFF00FFFF00000000848284848284848284848284848284D6D2CED6D2CE8482
+84848284848284D6D2CED6D2CE848684848284D6D2CED6D2CE848684D6D2CED6D2CE8482848C868C
+D6D2CED6D2CE848684D6D2CED6D2CE8C868C848684D6D2CED6D2CE8C868CD6D2CED6D2CE8486848C
+868CD6D2CED6D2CE848684D6D2CED6D2CE8C8A8C848684D6D2CED6D2CE8C8A8C8486848C8A8C8C86
+8C8C8A8C8486848C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8CD6D2CED6D2CE8C8A8C8C8A8C
+D6D2CED6D2CE8C8A8C8C8E8C8C8A8C8C8E8CD6D2CED6D2CE8C8A8C8C8E8C8C8A8C948E948C8A8CD6
+D2CED6D2CE948E94D6D2CED6D2CE8C8E8C948E94D6D2CED6D2CE8C8E8CD6D2CED6D2CE948E948C8E
+8CD6D2CED6D2CE948E94D6D2CED6D2CE8C8E8C949294D6D2CED6D2CE8C8E8C949294948E94949294
+D6D2CED6D2CE949294949294D6D2CED6D2CE949294949294D6D2CED6D2CE949294D6D2CED6D2CE94
+9294949294D6D2CED6D2CE949694D6D2CED6D2CE949294949694D6D2CED6D2CE9492949496949496
+949C969C9492949C969C9496949C969C9496949C969C9496949C969C9496949C969C9496949C9A9C
+9496949C969C9496949C9A9C9496949C9A9C9496949C9A9C9496949C9A9C9C969C9C9A9C9496949C
+9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A
+9C9C9E9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9CA59EA59C9A9C9C9E9C9C9E9CA59EA5
+9C9A9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A59C9E9CA5
+9EA59C9E9CA5A2A59C9E9CA5A2A59C9E9CA5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A5A2
+A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A6A5
+A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5ADA6ADA5A2A5A5A6A5A5A6A5ADA6ADA5A2A5AD
+A6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADA6ADA5A6
+A5ADAAADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADAAADADAAAD
+ADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAEADADAAADAD
+AEADADAAADADAEADADAAADADAEADADAAADB5AEB5ADAAADADAEADADAEADB5AEB5ADAAADB5AEB5ADAE
+ADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5AEB5ADAEADB5B2B5
+ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5B2B5B5B2B5B5B2B5B5
+B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2
+B5B5B6B5B5B2B5B5B6B5B5B2B5BDB6BDB5B2B5B5B6B5B5B6B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BD
+B5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BD
+BABDB5B6B5BDBABDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDBABDBDBABDBDBABDBDBABDBDBA
+BDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBD
+BDBABDBDBEBDBDBABDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5
+BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5C2C5BDBE
+BDC5C2C5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5FFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CE848284424142C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2CE000000000000
+D6D2CED6D2CE000000000000D6D2CED6D2CED6D2CE848284424142C5C2C5C5C2C5D6D2CED6D2CE84
+8284424142D6D2CEFFFFFFD6D2CED6D2CE8482848482848482840000FF8482840000FF0000FF8482
+840000FF848284000000000084000000000000000000FFFF00000000848284848284848284848684
+848284D6D2CED6D2CE8C868C848284848684D6D2CED6D2CE8482848C868CD6D2CED6D2CE848684D6
+D2CED6D2CE8C868C848684D6D2CED6D2CE8C868CD6D2CED6D2CE8486848C868CD6D2CED6D2CE8486
+84D6D2CED6D2CE8C8A8C848684D6D2CED6D2CE8C8A8CD6D2CED6D2CE8C868C8C8A8CD6D2CED6D2CE
+8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8E8C8C8A8CD6
+D2CED6D2CE948E948C8A8CD6D2CED6D2CE948E948C8A8C948E948C8A8CD6D2CED6D2CE948E948C8A
+8C948E948C8E8C948E94D6D2CED6D2CE8C8E8CD6D2CED6D2CE948E948C8E8CD6D2CED6D2CE949294
+D6D2CED6D2CE8C8E8C949294D6D2CED6D2CE948E94D6D2CED6D2CE949294948E94D6D2CED6D2CE94
+9294949294949294949294D6D2CED6D2CE949294949294D6D2CED6D2CE949694949294D6D2CED6D2
+CE9C969CD6D2CED6D2CE9492949C969CD6D2CED6D2CE949294D6D2CED6D2CE9C969C949294D6D2CE
+D6D2CE9C969C9496949C969C9496949C969C9496949C969C9496949C969C9496949C9A9C9C969C9C
+9A9C9496949C9A9C9C969C9C9A9C9C969C9C9A9C9C969C9C9A9C9C969C9C9A9C9C9A9C9C9A9C9C9A
+9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9CA59EA5
+9C9A9C9C9E9C9C9A9CA59EA59C9A9CA59EA59C9A9CA59EA59C9A9CA59EA59C9A9CA59EA59C9E9CA5
+9EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A5A59EA5A5A2A59C9E
+9CA5A2A5A59EA5A5A2A5A59EA5A5A2A5A59EA5A5A2A5A59EA5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5
+A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5ADA6ADA5A2A5A5
+A6A5A5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6
+A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAAD
+ADA6ADADAAADADA6ADADAAADADA6ADADAAADADA6ADADAAADADAAADADAAADADAAADADAAADADAAADAD
+AAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADB5AEB5ADAAADADAEADADAA
+ADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5
+ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5AEB5B5
+B2B5B5AEB5B5B2B5B5AEB5B5B2B5B5AEB5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2
+B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5BDB6BDB5B2B5B5B6B5B5B2B5BDB6BD
+B5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BD
+B6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDB6BDBDBABDBDB6
+BDBDBABDBDB6BDBDBABDBDB6BDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABD
+BDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5
+BEC5BDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBE
+BDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5BEC5C5C2C5C5BEC5C5C2C5
+C5BEC5C5C2C5C5BEC5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5
+C2C5C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CE000000000000000000000000000000000000D6D2
+CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE000000D6D2CED6D2CE848284424142C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6
+D2CE000000000000D6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CE848284424142C5C2
+C5C5C2C5D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284848284000000848284
+8482848482840000FF84828484828484828400000000000000000000000000000000000000000084
+8284848284848284848284848284D6D2CED6D2CE848284848284848284D6D2CED6D2CE8482848482
+84D6D2CED6D2CE848684848284D6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CE
+D6D2CED6D2CE8486848C868C848684D6D2CED6D2CED6D2CED6D2CED6D2CE848684D6D2CED6D2CE8C
+868C848684D6D2CED6D2CE8C8A8C8486848C8A8C8486848C8A8C8C868C8C8A8C8486848C8A8C8C8A
+8C8C8A8C8C8A8CD6D2CED6D2CED6D2CED6D2CE8C8A8C8C8A8CD6D2CED6D2CED6D2CED6D2CE8C8E8C
+8C8A8CD6D2CED6D2CED6D2CED6D2CED6D2CE8C8A8CD6D2CED6D2CE8C8E8C8C8E8CD6D2CED6D2CED6
+D2CED6D2CED6D2CE8C8E8CD6D2CED6D2CE948E948C8E8CD6D2CED6D2CE9492948C8E8CD6D2CED6D2
+CED6D2CED6D2CED6D2CE8C8E8C9492948C8E8C949294D6D2CED6D2CE8C8E8C949294D6D2CED6D2CE
+949294949294D6D2CED6D2CE949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE949694D6D2CED6
+D2CED6D2CED6D2CED6D2CE9496949492949C969C9492949496949496949C969C9492949C969C9496
+949C969C9496949C969C9496949C969C9496949C969C9496949C9A9C9496949C969C9496949C9A9C
+9496949C9A9C9496949C9A9C9496949C9A9C9C969C9C9A9C9496949C9A9C9C9A9C9C9A9C9C9A9C9C
+9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A
+9C9C9E9C9C9A9C9C9E9C9C9A9CA59EA59C9A9C9C9E9C9C9E9CA59EA59C9A9CA59EA59C9E9CA59EA5
+9C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A59C9E9CA59EA59C9E9CA5A2A59C9E9CA5
+A2A59C9E9CA5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2
+A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5A5A6A5
+A5A2A5A5A6A5A5A2A5ADA6ADA5A2A5A5A6A5A5A6A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5AD
+A6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADAAADA5A6
+A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADAAADADAAADADAAADADAAADADAAADADAAAD
+ADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAEADADAAADADAEADADAAADADAEADADAAADAD
+AEADADAAADB5AEB5ADAAADADAEADADAEADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAE
+ADB5AEB5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5
+ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5
+B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2
+B5BDB6BDB5B2B5B5B6B5B5B6B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BD
+B5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BD
+BABDBDB6BDBDBABDB5B6B5BDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBA
+BDBDBABDBDBABDBDBABDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDC5BEC5
+BDBABDBDBEBDBDBEBDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5
+BEC5BDBEBDC5C2C5BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5C5BE
+C5C5C2C5BDBEBDC5C2C5C5C2C5C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CE000000000000000000
+000000000000000000D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE00000000
+0000000000000000000000000000000000000000000000D6D2CED6D2CE848284424142C5C2C5C5C2
+C5FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284424142C5C2C5C5C2C5D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE84
+82848482848482840000008482840000000000008482840000008482840000008482848482848482
+848482848482840000008482848482848482848482848482848486848482848482848482848C868C
+8482848486848482848C868C8482848C868C8482848C868C8486848C868C8482848C868C8486848C
+868C8486848C868C8486848C868C8486848C868C8486848C868C8486848C8A8C8C868C8C8A8C8486
+848C8A8C8C868C8C8A8C8486848C8A8C8C868C8C8A8C8C868C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C
+8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8E8C8C8A8C8C8A8C8C8A8C948E948C8A8C8C
+8E8C8C8A8C948E948C8A8C948E948C8A8C948E948C8E8C948E948C8A8C948E948C8E8C948E948C8E
+8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C949294948E949492948C8E8C949294
+948E949492948C8E8C949294948E94949294948E9494929494929494929494929494929494929494
+92949492949492949492949492949492949496949492949492949492949C969C9492949496949492
+949C969C949294D6D2CED6D2CE9C969C9496949C969C9492949C969C9496949C969C9496949C969C
+9496949C969C9496949C969C9496949C969C9496949C9A9C9C969C9C9A9C9496949C9A9C9C969C9C
+9A9C9496949C9A9C9C969C9C9A9C9C969C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A
+9C9C9A9C9C9A9C9C9A9C9C9A9C9C9E9C9C9A9C9C9A9C9C9A9CA59EA59C9A9C9C9E9C9C9A9CA59EA5
+9C9A9CA59EA59C9A9CA59EA59C9E9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5
+9EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E
+9CA5A2A5A59EA5A5A2A5A59EA5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5
+A5A2A5A5A2A5A5A2A5A5A6A5A5A2A5A5A2A5A5A2A5ADA6ADA5A2A5A5A6A5A5A2A5ADA6ADA5A2A5AD
+A6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6
+A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAAD
+ADA6ADADAAADADA6ADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADAD
+AAADADAAADADAEADADAAADADAAADADAAADB5AEB5ADAAADADAEADADAAADB5AEB5ADAAADB5AEB5ADAA
+ADB5AEB5ADAEADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5
+ADAEADB5AEB5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5AEB5B5
+B2B5B5AEB5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2
+B5B5B2B5B5B2B5B5B2B5B5B2B5BDB6BDB5B2B5B5B6B5B5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BD
+B5B2B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BD
+B6BDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDB6BDBDBABDBDB6
+BDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABD
+BDBABDBDBABDBDBABDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBABDC5
+BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBE
+BDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5BEC5C5C2C5C5BEC5C5C2C5
+C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFF
+FFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142C5C2C5C5C2C5FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE848284424142C5C2C5C5C2C5D6D2CED6D2CE848284424142D6D2
+CEFFFFFFD6D2CED6D2CE848284848284848284848284848284848284000000848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848486848482848486848482848486848482848486848482
+848C868C8482848486848486848C868C8482848C868C8486848C868C8486848C868C8486848C868C
+8486848C868C8486848C8A8C8486848C868C8486848C8A8C8486848C8A8C8486848C8A8C8486848C
+8A8C8C868C8C8A8C8486848C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A
+8C8C8A8C8C8A8C8C8A8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C948E94
+8C8A8C8C8E8C8C8E8C948E948C8A8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C94
+8E948C8E8C9492948C8E8C948E948C8E8C9492948C8E8C9492948C8E8C9492948C8E8C949294948E
+949492948C8E8C949294949294949294949294949294949294949294949294949294949294949294
+949294949294949294949694949294949694D6D2CED6D2CE9492949496949492949C969C94929494
+96949496949C969C9492949C969C9496949C969C9496949C969C9496949C969C9496949C969C9496
+949C9A9C9496949C969C9496949C9A9C9496949C9A9C9496949C9A9C9496949C9A9C9C969C9C9A9C
+9496949C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C
+9A9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9CA59EA59C9A9C9C9E9C9C9E
+9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A5
+9C9E9CA59EA59C9E9CA5A2A59C9E9CA5A2A59C9E9CA5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5
+A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2
+A5A5A6A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2A5ADA6ADA5A2A5A5A6A5A5A6A5ADA6AD
+A5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5AD
+A6ADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADAA
+ADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAEAD
+ADAAADADAEADADAAADADAEADADAAADADAEADADAAADB5AEB5ADAAADADAEADADAEADB5AEB5ADAAADB5
+AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5AEB5ADAE
+ADB5B2B5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5B2B5B5B2B5
+B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B6B5B5B2B5B5
+B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5BDB6BDB5B2B5B5B6B5B5B6B5BDB6BDB5B2B5BDB6BDB5B6
+B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDB6BDB5B6B5BDBABD
+B5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDBABDBDBABDBDBABDBD
+BABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBEBDBDBABDBDBEBDBDBA
+BDBDBEBDBDBABDBDBEBDBDBABDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5
+BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5
+C2C5BDBEBDC5C2C5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2
+C5FFFFFF848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284424142FFFFFF84828484828484828484828484828484828484828484828484828484
+8284848284848284848284848284424142C5C2C5C5C2C5FFFFFF8482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284424142C5C2C5C5C2C5D6D2CE
+D6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE84828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+848486848482848482848482848C868C8482848486848482848C868C8482848C868C8482848C868C
+8486848C868C8482848C868C8486848C868C8486848C868C8486848C868C8486848C868C8486848C
+868C8486848C8A8C8C868C8C8A8C8486848C8A8C8C868C8C8A8C8C868C8C8A8C8C868C8C8A8C8C86
+8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8E8C
+8C8A8C8C8A8C8C8A8C948E948C8A8C8C8E8C8C8A8C948E948C8A8C948E948C8A8C948E948C8E8C94
+8E948C8A8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E
+8C949294948E949492948C8E8C949294948E94949294948E94949294948E94949294948E94949294
+94929494929494929494929494929494929494929494929494929494929494929494969494929494
+92949492949C969C9492949496949492949C969C9492949C969C9492949C969C9496949C969C9492
+949C969C9496949C969C9496949C969C9496949C969C9496949C969C9496949C969C9496949C9A9C
+9C969C9C9A9C9496949C9A9C9C969C9C9A9C9C969C9C9A9C9C969C9C9A9C9C969C9C9A9C9C9A9C9C
+9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A
+9CA59EA59C9A9C9C9E9C9C9A9CA59EA59C9A9CA59EA59C9A9CA59EA59C9A9CA59EA59C9A9CA59EA5
+9C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A5A59EA5A5
+A2A59C9E9CA5A2A5A59EA5A5A2A5A59EA5A5A2A5A59EA5A5A2A5A59EA5A5A2A5A5A2A5A5A2A5A5A2
+A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5ADA6AD
+A5A2A5A5A6A5A5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A2A5ADA6ADA5A6A5AD
+A6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADADA6ADADAAADA5A6
+A5ADAAADADA6ADADAAADADA6ADADAAADADA6ADADAAADADA6ADADAAADADAAADADAAADADAAADADAAAD
+ADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADB5AEB5ADAAADAD
+AEADADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAE
+ADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5
+B5AEB5B5B2B5B5AEB5B5B2B5B5AEB5B5B2B5B5AEB5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5
+B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5BDB6BDB5B2B5B5B6B5B5B2
+B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BD
+B5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDB6BDBD
+BABDBDB6BDBDBABDBDB6BDBDBABDBDB6BDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBA
+BDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDC5BEC5BDBABDBDBEBDBDBABDC5BEC5
+BDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5
+BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5BEC5C5C2C5C5BE
+C5C5C2C5C5BEC5C5C2C5C5BEC5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5
+C5C2C5C5C2C5C5C2C5C5C2C542414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142C5C2C5C5C2C5424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+4142C5C2C5C5C2C5D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE8482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848486848482848486848482848486848482848486848482848C868C8482848486848486
+848C868C8482848C868C8486848C868C8486848C868C8486848C868C8486848C868C8486848C8A8C
+8486848C868C8486848C8A8C8486848C8A8C8486848C8A8C8486848C8A8C8C868C8C8A8C8486848C
+8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A
+8C8C8E8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C8C8E8C8C8A8C948E948C8A8C8C8E8C8C8E8C948E94
+8C8A8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C9492948C8E8C94
+8E948C8E8C9492948C8E8C9492948C8E8C9492948C8E8C949294948E949492948C8E8C9492949492
+94949294949294949294949294949294949294949294949294949294949294949294949294949694
+9492949496949492949496949492949496949492949C969C9492949496949496949C969C9492949C
+969C9496949C969C9496949C969C9496949C969C9496949C969C9496949C9A9C9496949C969C9496
+949C9A9C9496949C9A9C9496949C9A9C9496949C9A9C9C969C9C9A9C9496949C9A9C9C9A9C9C9A9C
+9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9E9C9C9A9C9C
+9E9C9C9A9C9C9E9C9C9A9C9C9E9C9C9A9CA59EA59C9A9C9C9E9C9C9E9CA59EA59C9A9CA59EA59C9E
+9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A59C9E9CA59EA59C9E9CA5A2A5
+9C9E9CA5A2A59C9E9CA5A2A59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A5A2A5A5A2A5A5A2A5A5
+A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A6A5A5A2A5A5A6A5A5A2
+A5A5A6A5A5A2A5A5A6A5A5A2A5ADA6ADA5A2A5A5A6A5A5A6A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6AD
+A5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5AD
+AAADA5A6A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6A5ADAAADADAAADADAAADADAAADADAAADADAA
+ADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAEADADAAADADAEADADAAADADAEAD
+ADAAADADAEADADAAADB5AEB5ADAAADADAEADADAEADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5
+AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5B2B5ADAE
+ADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5
+B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5B6B5B5B2B5B5
+B6B5B5B2B5BDB6BDB5B2B5B5B6B5B5B6B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6
+B5BDB6BDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABD
+B5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBD
+BABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBABDBDBEBDBDBA
+BDC5BEC5BDBABDBDBEBDBDBEBDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5
+BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5BEC5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5
+C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2
+C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5
+C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5
+C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2
+C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CE
+D6D2CE84828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848486848482848482848482
+848C868C8482848486848482848C868C8482848C868C8482848C868C8486848C868C8482848C868C
+8486848C868C8486848C868C8486848C868C8486848C868C8486848C868C8486848C8A8C8C868C8C
+8A8C8486848C8A8C8C868C8C8A8C8486848C8A8C8C868C8C8A8C8C868C8C8A8C8C8A8C8C8A8C8C8A
+8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8A8C8C8E8C8C8A8C8C8A8C8C8A8C948E94
+8C8A8C8C8E8C8C8A8C948E948C8A8C948E948C8A8C948E948C8E8C948E948C8A8C948E948C8E8C94
+8E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C948E948C8E8C949294948E949492948C8E
+8C949294948E949492948C8E8C949294948E94949294948E94949294949294949294949294949294
+9492949492949492949492949492949492949492949496949492949492949492949C969C94929494
+96949492949C969C9492949C969C9492949C969C9496949C969C9492949C969C9496949C969C9496
+949C969C9496949C969C9496949C969C9496949C969C9496949C9A9C9C969C9C9A9C9496949C9A9C
+9C969C9C9A9C9496949C9A9C9C969C9C9A9C9C969C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C
+9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9A9C9C9E9C9C9A9C9C9A9C9C9A9CA59EA59C9A9C9C9E9C9C9A
+9CA59EA59C9A9CA59EA59C9A9CA59EA59C9E9CA59EA59C9A9CA59EA59C9E9CA59EA59C9E9CA59EA5
+9C9E9CA59EA59C9E9CA59EA59C9E9CA59EA59C9E9CA5A2A5A59EA5A5A2A59C9E9CA5A2A5A59EA5A5
+A2A59C9E9CA5A2A5A59EA5A5A2A5A59EA5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2A5A5A2
+A5A5A2A5A5A2A5A5A2A5A5A2A5A5A6A5A5A2A5A5A2A5A5A2A5ADA6ADA5A2A5A5A6A5A5A2A5ADA6AD
+A5A2A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A2A5ADA6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5AD
+A6ADA5A6A5ADA6ADA5A6A5ADA6ADA5A6A5ADAAADA5A6A5ADAAADA5A6A5ADAAADADA6ADADAAADA5A6
+A5ADAAADADA6ADADAAADADA6ADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAADADAAAD
+ADAAADADAAADADAAADADAEADADAAADADAAADADAAADB5AEB5ADAAADADAEADADAAADB5AEB5ADAAADB5
+AEB5ADAAADB5AEB5ADAEADB5AEB5ADAAADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAEADB5AEB5ADAE
+ADB5AEB5ADAEADB5AEB5ADAEADB5B2B5ADAEADB5B2B5ADAEADB5B2B5B5AEB5B5B2B5ADAEADB5B2B5
+B5AEB5B5B2B5B5AEB5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5
+B2B5B5B2B5B5B2B5B5B2B5B5B2B5B5B2B5BDB6BDB5B2B5B5B6B5B5B2B5BDB6BDB5B2B5BDB6BDB5B2
+B5BDB6BDB5B2B5BDB6BDB5B2B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BDB5B6B5BDB6BD
+B5B6B5BDB6BDB5B6B5BDBABDB5B6B5BDBABDB5B6B5BDBABDBDB6BDBDBABDB5B6B5BDBABDBDB6BDBD
+BABDBDB6BDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBABDBDBA
+BDBDBABDBDBABDBDBABDBDBABDC5BEC5BDBABDBDBEBDBDBABDC5BEC5BDBABDC5BEC5BDBABDC5BEC5
+BDBABDC5BEC5BDBABDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5BEC5BDBEBDC5
+BEC5BDBEBDC5C2C5BDBEBDC5C2C5BDBEBDC5C2C5C5BEC5C5C2C5BDBEBDC5C2C5C5BEC5C5C2C5C5BE
+C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5
+C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5
+C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2
+C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5
+C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5C5C2C5D6D2CED6D2CE84828442
+4142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFF
+FFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284848284848284848284848284D6D2CE848284D6
+D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284848284D6D2CED6D2CED6D2CE848284
+848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482848482
+84848284848284848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2
+CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6
+D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284848284D6
+D2CED6D2CED6D2CE848284848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284D6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284D6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CED6D2CE84828484828484
+8284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284D6D2CE848284D6D2CE848284D6D2CE848284D6D2CED6D2CE848284848284848284
+D6D2CED6D2CE848284848284848284848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84848284848284D6D2CED6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CED6D2CE848284848284
+848284D6D2CED6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CE8482
+84848284848284D6D2CED6D2CE848284848284848284848284D6D2CED6D2CE848284D6D2CED6D2CE
+848284848284848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CE8482848482
+84848284D6D2CED6D2CE848284D6D2CE848284848284848284848284D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284848284848284848284848284D6D2CE848284D6D2CE848284D6D2
+CE848284D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CE848284D6D2CE848284D6D2CED6
+D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CE848284D6
+D2CE848284D6D2CED6D2CED6D2CE848284D6D2CE848284848284D6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CE848284D6
+D2CE848284D6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284848284848284848284848284848284
+D6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CE84
+8284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CE
+848284D6D2CE848284D6D2CE848284848284848284848284848284D6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CE848284D6D2
+CED6D2CE848284D6D2CED6D2CE848284848284848284848284D6D2CE848284D6D2CED6D2CED6D2CE
+848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CE848284848284848284848284D6D2CED6D2CE8482
+84D6D2CE848284D6D2CED6D2CE848284848284848284848284848284D6D2CE848284D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CE848284848284848284848284D6D2CE848284D6D2
+CED6D2CED6D2CE848284D6D2CE848284D6D2CE848284848284848284848284848284D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6
+D2CED6D2CED6D2CE848284D6D2CE848284848284848284848284848284D6D2CE848284D6D2CE8482
+84D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284
+424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6
+D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284
+D6D2CED6D2CE848284D6D2CED6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CE84
+8284D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CE
+848284D6D2CED6D2CE848284D6D2CE848284D6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6
+D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CE
+848284D6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CE848284D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284D6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CE848284D6D2CE
+D6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CED6D2
+CED6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CE84
+8284D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CE848284D6D2
+CED6D2CED6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CE84
+8284D6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CE848284D6D2
+CE848284D6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6
+D2CED6D2CED6D2CE848284D6D2CE848284D6D2CE848284D6D2CED6D2CED6D2CE848284D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE84
+8284D6D2CED6D2CE848284848284848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CE848284
+D6D2CED6D2CE848284848284848284848284D6D2CE848284848284848284848284D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482848482
+84848284848284D6D2CED6D2CE848284848284848284848284D6D2CED6D2CED6D2CE848284D6D2CE
+D6D2CED6D2CED6D2CE848284848284848284D6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84D6D2CED6D2CED6D2CED6D2CE848284848284848284848284D6D2CE848284848284848284848284
+D6D2CED6D2CE848284D6D2CED6D2CE848284848284848284D6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2
+CE848284D6D2CED6D2CE848284848284848284D6D2CED6D2CE848284D6D2CE848284848284848284
+848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142
+D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284848284848284848284848284848284D6D2CED6D2CE848284424142D6D2CEFFFFFFD6
+D2CED6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CED6D2CE8482
+84424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142D6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CE
+FFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284
+424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6
+D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CED6D2CE000000000000000000000000000000000000D6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000000000000000D6
+D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE00000094929494929494929494929494
+9294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE9492949492
+94949294949294000000949294D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE737173737173737173D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE737173D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFF
+FFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284848284848284D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE0000009492
+94D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CE848284424142FFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE737173FFFFFFFFFFFFFFFFFF737173D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE737173737173FFFFFF737173737173D6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CEFF
+FFFFFFFFFF848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284848284D6D2CE8482848482
+84D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000D6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2
+CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE737173FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF737173D6D2CED6D2CED6D2CE737173737173FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF73
+7173D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE848284D6D2CEFFFFFF848284D6D2CED6D2CE848284D6D2CED6D2CED6D2CE848284848284D6D2CE
+FFFFFF848284D6D2CE848284848284D6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6
+D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284
+424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFF
+D6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE949294000000DEDBDEFFFFFFFFFFFFD6D7D6000000949294D6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294000000DEDBDEFFFFFFFFFFFFD6D7D600000094
+9294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CED6D2CE000000949294D6D2CED6D2CE0000000000000000000000
+00D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000D6D2CED6D2CED6D2CE
+000000949294D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE737173FF
+FFFF000000000000000000000000FFFFFFFFFFFF737173737173737173FFFFFF0000000000000000
+00000000FFFFFFFFFFFF737173D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284D6D2CE848284848284848284848284D6D2CED6D2CE84828484828484
+8284D6D2CE848284848284848284D6D2CE848284D6D2CE848284FFFFFFD6D2CED6D2CED6D2CE8482
+84424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00
+0000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFF949294949294FFFFFFFFFFFF000000
+949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFF9492
+94949294FFFFFFFFFFFF000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284
+424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00
+0000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000949294D6D2CED6D2CE
+000000000000000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00000000000000
+0000949294D6D2CED6D2CE000000949294D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2
+CED6D2CED6D2CE737173FFFFFF000000000000000000949294949294FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF000000000000000000949294FFFFFF737173D6D2CED6D2CED6D2CED6D2CE84828442
+4142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFF848284848284848284848284FFFF
+FFD6D2CE848284FFFFFFFFFFFFFFFFFF848284848284848284848284D6D2CEFFFFFF848284FFFFFF
+D6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE000000000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000000000949294D6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000DEDBDEFFFFFF949294FFFFFFFF
+FFFFFFFFFFFFFFFFDEDBDE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000
+DEDBDEFFFFFF949294FFFFFFFFFFFFFFFFFFFFFFFFDEDBDE000000D6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294949294949294D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6
+D2CE949294D6D2CED6D2CE000000000000000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE000000000000000000949294D6D2CED6D2CED6D2CE949294D6D2CED6D2CE848284424142
+FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE737173FFFFFF000000000000000000949294FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000949294FFFFFF737173D6D2CED6D2
+CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE848284848284848284
+848284848284848284FFFFFF848284848284FFFFFFD6D2CED6D2CE848284848284848284848284FF
+FFFFD6D2CE848284FFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000949294
+D6D2CED6D2CED6D2CED6D2CED6D2CE000000000000949294949294949294949294000000000000D6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2
+CE000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFF
+FF949294FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE000000FFFFFF949294FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000009492
+94D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFF
+FFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294949294000000D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE000000D6D2CE949294000000949294D6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE737173FFFFFF0000009492
+94949294000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF949294000000949294
+FFFFFF737173D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6
+D2CE848284FFFFFF848284848284848284848284848284D6D2CE848284FFFFFFD6D2CED6D2CED6D2
+CE848284848284848284848284D6D2CE848284FFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000949294949294D6D2CED6D2
+CED6D2CE000000000000949294D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CED6D2CED6D2CED6D2CE000000000000000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2
+CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294D6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE0000
+00949294D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294D6
+D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CE949294D6D2CED6D2CE949294D6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+737173FFFFFFFFFFFF949294FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF94
+9294FFFFFFFFFFFF949294FFFFFF737173D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFF848284848284FFFFFFFFFFFFD6D2CE
+848284848284848284D6D2CED6D2CEFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFD6D2CED6D2CED6
+D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE000000000000000000949294D6D2CED6D2CED6D2CED6D2CE000000
+949294D6D2CED6D2CED6D2CED6D2CE000000000000949294D6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000DEDBDEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFDEDBDE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000DEDBDEFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFDEDBDE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2CE
+D6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294D6D2CED6D2CED6D2CED6D2CE949294D6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE737173FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF949294FFFFFFFFFF
+FFFFFFFFFFFFFF949294FFFFFFFFFFFFFFFFFFFFFFFF737173D6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CEFF
+FFFFFFFFFFD6D2CED6D2CED6D2CEFFFFFFFFFFFF848284D6D2CED6D2CED6D2CED6D2CE848284D6D2
+CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000D6D2CED6
+D2CED6D2CED6D2CED6D2CE949294D6D2CED6D2CED6D2CED6D2CE000000000000949294D6D2CED6D2
+CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000000000
+000000000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294949294D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE737173FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF737173D6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE848284D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE
+D6D2CED6D2CE848284FFFFFFD6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000000000
+00000000000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000
+949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6
+D2CED6D2CE000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000
+00949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CE
+D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00
+0000000000000000DEDBDEFFFFFFFFFFFFDEDBDE000000949294949294D6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE000000000000000000DEDBDEFFFFFFFFFFFFDEDBDE00000094929494
+9294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE000000000000949294949294949294949294000000949294949294
+949294949294000000000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84828442
+4142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE737173FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF737173D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE848284848284848284848284FFFFFFD6D2CED6D2CED6D2CED6D2CE8482844241
+42D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE000000000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFF
+FFD6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000000000949294D6D2CED6D2CE
+D6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84828442
+4142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE000000000000000000949294000000000000000000000000949294949294D6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000000000000000009492940000000000000000
+00000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142
+FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6
+D2CE000000949294D6D2CED6D2CED6D2CE000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE737173737173FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF737173D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284848284D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CEFFFFFFFFFFFF848284FFFFFFD6D2CED6D2CE
+D6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000000000949294D6D2CED6D2
+CED6D2CED6D2CED6D2CE000000000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE00000000000000000000000000
+0000000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000949294949294D6D2CE94929494929494
+9294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFF
+FFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000949294
+949294D6D2CE949294949294949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE949294D6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CE949294D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFF
+FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF737173D6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CEFFFFFF848284D6D2CED6D2CED6D2CED6D2CE848284848284D6D2CEFFFFFFD6D2CED6D2CE84
+8284FFFFFFD6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000
+000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000000000949294D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE0000
+00000000000000000000000000000000949294D6D2CED6D2CED6D2CED6D2CE000000949294D6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000949294949294D6D2
+CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00000000
+0000000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CE949294D6D2CE
+D6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2
+CE000000D6D2CE949294FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFF737173
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284848284D6D2CEFFFFFFFFFF
+FFD6D2CED6D2CED6D2CE848284FFFFFFD6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00
+0000000000000000000000000000000000949294D6D2CED6D2CED6D2CED6D2CE0000000000009492
+94D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CE000000000000000000000000000000000000000000D6D2CED6D2CED6D2CED6
+D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFF
+FFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000
+949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2D6D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE000000000000000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000000000000000000000
+00000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000D6
+D2CE949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000949294D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE000000000000000000D6D2CE949294D6D2CE737173FFFFFFFFFFFFFFFFFFFFFFFF00000000
+0000000000949294737173D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284848284848284848284D6D2CED6D2CED6D2CE848284D6D2CE
+FFFFFFFFFFFF848284848284848284848284D6D2CE848284FFFFFFD6D2CED6D2CED6D2CED6D2CE84
+8284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE000000000000000000000000000000000000000000D6D2CED6D2CED6D2CE
+D6D2CED6D2CE949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84828442
+4142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE0000000000000000009492940000000000000000
+00949294D6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00
+0000000000000000949294949294D6D2CED6D2CED6D2CED6D2CE0000000000000000000000000000
+00000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE000000000000000000949294949294D6D2CED6D2CED6D2CED6D2CE00
+0000000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE000000000000000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2
+CE000000000000000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000
+000000949294D6D2CED6D2CE000000D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000949294D6D2CED6D2CED6D2CE737173FFFF
+FFFFFFFFFFFFFF000000000000000000949294737173D6D2CED6D2CED6D2CED6D2CED6D2CE848284
+424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284848284848284848284D6
+D2CED6D2CE848284848284D6D2CED6D2CE848284848284848284848284848284848284FFFFFFD6D2
+CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00000000000000000094929400000000000000
+0000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000000000949294
+949294D6D2CE000000000000000000D6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE949294000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE000000
+000000000000000000000000000000D6D2D6D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84828442
+4142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294000000949294949294D6D2CED6D2
+CED6D2CED6D2CED6D2CE000000000000000000000000000000000000D6D2D6D6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE
+000000949294D6D2CED6D2CE000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE000000000000000000000000949294D6D2CED6D2CE000000949294D6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000D6D2CE
+D6D2CED6D2CED6D2CE737173FFFFFF000000000000000000000000949294737173D6D2CED6D2CED6
+D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84848284848284848284FFFFFFD6D2CED6D2CE848284848284D6D2CE848284848284848284848284
+FFFFFF848284FFFFFFD6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000000000009492
+94949294D6D2CE000000000000000000D6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6
+D2CE000000949294949294D6D2CED6D2CED6D2CE949294000000949294D6D2CE0000000000000000
+00D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE
+FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294949294D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2D6000000000000D6D2D6D6D2D6D6D2D6D6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294
+949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2D6D6D2D6D6D2D6D6D2D6D6D2D6D6
+D2D6D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294D6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FF
+FFFFD6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CE949294949294949294949294D6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE949294949294949294949294D6D2CED6D2CE000000949294
+D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE94
+9294949294949294949294D6D2CED6D2CED6D2CED6D2CE737173FFFFFF9492949492949492949492
+94737173D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284D6D2CE848284848284848284FFFFFFD6D2CED6D2CED6D2CE84828484828484
+8284848284848284848284FFFFFF848284FFFFFFD6D2CED6D2CED6D2CED6D2CE848284424142D6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE000000949294949294D6D2CED6D2CED6D2CE949294000000949294D6D2CED6D2CE00000000
+0000949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE949294D6D2CED6D2CED6D2CED6D2CED6D2CE949294949294
+D6D2CED6D2CE949294949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6
+D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2D6D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE000000949294D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE737173FFFFFF
+FFFFFF737173737173737173D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CE848284D6D2CEFFFFFF848284FFFFFFD6D2CED6D2
+CED6D2CED6D2CE848284FFFFFF848284848284848284848284D6D2CEFFFFFFD6D2CED6D2CED6D2CE
+D6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE9492
+94D6D2CED6D2CED6D2CE949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2D6D6D2D6D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000949294D6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE737173737173D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284D6D2CEFFFFFFD6D2CE
+D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE848284848284FFFFFFFFFFFFFFFFFF848284D6
+D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2
+CED6D2CE000000000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE000000000000000000000000000000000000949294D6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFFFFF
+FFD6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2
+CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284
+424142FFFFFFD6D2CED6D2CED6D2CED6D2CE949294949294949294949294949294949294D6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE9492949492949492949492949492
+94949294D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84828442
+4142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284
+424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142
+FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CEFFFFFF8482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284848284848284848284848284848284848284848284848284848284848284424142FF
+FFFF8482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284848284424142FFFFFF84828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284424142FFFFFF848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+8284848284848284848284848284848284848284848284848284848284848284848284424142FFFF
+FF848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+8284848284848284424142FFFFFF8482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284848284848284848284848284848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CEFFFFFF8482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284848284848284848284848284424142FFFFFF84828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284424142D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+4142424142424142424142424142424142424142424142424142424142424142424142D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+4142424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2
+CED6D2CE848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284FFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142
+D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+4142424142424142424142424142D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600089600089600089600D6
+D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CE
+D6D2CE08960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284
+424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFF
+FFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6
+D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE8482
+84424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFF
+FFD6D2CED6D2CE089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2
+CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CE
+FFFFFFD6D2CED6D2CED6D2CE84828442414284828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+8284848284848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600089600089600D6D2CED6
+D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142
+848284FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6
+D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6
+D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE8482844241
+42D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2
+CED6D2CE089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482
+84424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CE
+FFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFF
+D6D2CED6D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE84
+8284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284
+FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFF
+FFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6
+D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFF
+FFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2
+CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CE000000
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE5A5D5AFFFFFFFFFFFFFFFFFF5A5D5AD6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600D6D2CE
+D6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFFD6D2CED6
+D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE5A5D5AFFFFFFFFFFFFFFFF
+FF5A5D5A000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2
+CE089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241
+42848284FFFFFFD6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE000000000000000000000000D6D2CED6D2CED6D2CED6D2CE000000000000000000D6D2CE00
+0000D6D2CED6D2CED6D2CE000000000000000000000000D6D2CED6D2CED6D2CE000000D6D2CE0000
+00000000D6D2CED6D2CED6D2CED6D2CE000000000000000000D6D2CE000000D6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+5A5D5AFFFFFFFFFFFFFFFFFF5A5D5A9492949492949492949492945A5D5AD6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFF
+D6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+0896000896000896000896000896000896000896000896000896000896000896005265E608960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CE
+D6D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2
+CED6D2CED6D2CE000000000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CE
+D6D2CE000000000000D6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CE00000000
+0000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE5A5D5AFFFFFFFFFFFFFFFFFF5A5D5A9492949492949492949492945A5D
+5AD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896005265E65265E65265E65265E65265E65265E65265
+E65265E65265E6089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE84828442
+4142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2
+CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000
+D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6
+D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2
+CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE5A5D5AFFFFFFFFFFFFFFFFFF5A5D5A949294
+9492949492949492945A5D5AD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E608960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFF
+D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00000000000000
+0000000000000000000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2
+CE000000000000000000000000000000000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000
+D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE5A5D5A5A5D5A5A
+5D5A5A5D5A5A5D5A9492949492949492949492945A5D5AD6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6
+D2CED6D2CE0896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+000896000896000896000896000896000896000896000896005265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84
+8284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE
+D6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6
+D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE5A5D5A9492949492949492949492949492949492949492945A5D5AD6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6
+D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2
+CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+0896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFF
+FFD6D2CED6D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CE000000D6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE00
+0000D6D2CED6D2CED6D2CE000000000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CE
+000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE5A5D5A94929494929494929494929494929494929494
+92945A5D5AD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+0896000896000896000896000896000896000896005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E60896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE
+848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6
+D2CED6D2CE000000000000000000000000000000000000D6D2CED6D2CE0000000000000000000000
+00D6D2CED6D2CED6D2CED6D2CE000000000000000000D6D2CE000000D6D2CED6D2CED6D2CE000000
+000000000000000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6
+D2CE000000000000000000D6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE5A5D5A5A5D5A5A5D5A5A5D
+5A5A5D5A5A5D5A5A5D5A5A5D5A5A5D5AD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+0896000896000896000896000896000896000896000896000896000896000896000896005265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241428482
+84FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CE
+FFFFFFD6D2CED6D2CE08960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E60000000000005265E60000005265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E608960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE
+D6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FF
+FFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896
+000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960000000008960008960052
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000000000000000
+00000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E6089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6
+D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600
+0896000896000896000896000896000896000896005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E608960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+0896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E60000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E60000000000000000000000000000005265E60000000000
+0000000000E30000E3000000000000000000000000005265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E608960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600089600089600089600089600D6D2
+CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284FFFFFFD6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6
+D2CE0896000896000896000896000896000896000896000896000896000896005265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E60000000000005265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000E700000000
+00000000000000000000000000000000000000000000000000000000DF000000005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442
+4142848284FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284FFFFFFD6D2CEFFFF
+FFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600089600089600089600
+0896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600
+000000000000E30000000000000000000000000000E30000DF0000E30000E30000DF0000DF000000
+000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2
+CED6D2CED6D2CE848284424142848284FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008
+96000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E600000000000000E70000000000E30000E30000E30000E70000CE0000E700
+00DF0000DF0000DF000000000000005265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E60896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284
+424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442414284828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+8284848284848284848284848284FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896
+000896000896000896000896000896000896000896000896005265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E600000000000000000000DF0000DF0000E30000
+CA0000E30000BA0000E70000CA0000CE0000DF000000000000000000000000005265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E60000000000000000005265E65265E65265E60000000000000000005265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFF
+D6D2CED6D2CE0896000896000896000896000896000896000896000896000896000896005265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E60000000000005265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000
+0000E30000E70000DF0000CA0000E30000BA0000C20000BA0000D200000000000000000000000000
+0000000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E60000000000000000000000000000000000000000000000
+000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E608960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE
+84828442414284828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284848284848284848284848284848284848284848284848284848284848284848284D6
+D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896
+000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000CE000000000000
+000000000000005265E60000000000005265E60000000000000000005265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E600000000000000CA0000CA0000CA0000C20000D20000B60000E30000E30000000000
+000000E70000E70000C20000000000CA0000A6000000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000E70000DF0000D200
+0000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E6089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFF
+FFFFD6D2CED6D2CED6D2CE848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600
+0896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000000000000000
+000000000000000000000000FFFF00FFFF0000000000000000BA000000005265E600000000000052
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E600000000000000C20000CA0000CE0000BE0000B60000C2
+0000BA0000A60000000000000000C20000E70000000000BE0000DB0000D2000000005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000
+000000AA0000CA0000AA000000005265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E608960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2
+CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08
+96000896000896000896000896000896000896000896000896005265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600
+000008960000000000000000D200000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000000000
+000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000D200
+00CA0000BE0000D20000BE0000BA0000000000AA0000000000B60000C20000D70000000000D20000
+CE0000C2000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E6000000000000089A0000AA000000000000005265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2
+CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896000896005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E600000000000000DF0000AA00000000FFFF00FFFF00FFFF00FFFF00
+FFFF0000000000000000CA0000000000DB000000005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600
+000000000000000000DF0000E30000D20000E70000AA0000A60000000000BE0000A60000000000C2
+00009E0000000000000000B2000000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E60000000000000000000000000000005265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2
+CED6D2CE848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF424142FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008
+96000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E6000000000000000000000000FFFF00FF
+FF00FFFF00FFFF00000000000000FFFF00FFFF00000000000000089A000000000000005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E600000000E300000000009E0000C20000000000000000000000CA00
+00AE0000DF0000000000C20000D20000CA0000C2000000000000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E6000000000000089A000000005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E60896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142
+D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896
+000896000896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E60000000000005265E65265E60000
+0000E300000000FFFF00FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000
+00CA000896000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E600000000000000000000000000000000
+A60000000000AE00009E0000C600009E0000DB000000000000000000000000000000005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000000000000000
+0000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600089600089600089600D6
+D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CE
+D6D2CE0896000896000896000896000896000896000896000896000896005265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000
+089A00000000000000009E0000D700000000000000FFFF00FFFF00000000FFFF00FFFF00FFFF00FF
+FF0000000000000000000000AA0000AA000000000000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000
+0000000000E30000E70000BE0000000000CA0000D20000BA0000CA0008960000000000000000C600
+0000000000000000000000005265E65265E65265E65265E65265E65265E600000000000000000000
+000000000000DF0000000000000000CA000000005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284
+424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84828442
+4142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFF
+FFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896000896
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E600000000000000000000AA0000A20000D200000000FFFF00000000FFFF
+00FFFF00FFFF00000000000000FFFF00FFFF0000000000000000C6000000000000000000005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E60000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E600000000000000C20000000000000000C20000C60000DB0000BE0000C60000
+D700089A0000D70000BA0000000000AA000000000000005265E65265E65265E65265E65265E65265
+E600000000E70000000000E30000E30000000000CE0000C6000000000000005265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E6089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6
+D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142
+FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000000000000000000000000000D6D2
+CED6D2CE313131D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600
+0896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000000000000000
+000000000000000000FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000
+B2000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E60000005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E600000000DF0000000000DF00089A0000D2
+0000C20000DB0000D200089A0000B60000DB0000C20000CE00000000000000000000000000000000
+0000005265E65265E65265E600000000000000E30000000000000000000000B60000D200009E0000
+9E000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E608960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE8482
+84424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFF
+FFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294949294949294949294949294
+949294949294000000000000000000313131D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008
+96000896000896000896000896000896000896000896005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E60000000000005265E65265E65265E65265E6000000FFFF00000000FFFF00000000000000FFFF
+00FFFF00FFFF000000000000000000000000005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000
+00CA0000DB0000CA0000CE0000B60000B60000C20000C20000CE0000AA00089A0000BA0008960000
+00000000000000000000000000005265E65265E65265E60000000000000000000000000000000000
+0010920010920000CE000000005265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE000000000000000000000000000000000000000000000000000000000000000000D6D2CED6D2CE
+D6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE0000000000000000000000000000000000000000000000000000
+00000000000000D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00000000000000000000000000
+0000000000000000000000000000000000000000D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE000000000000000000000000000000000000000000000000000000000000000000D6D2CED6
+D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00000094929494929494
+9294949294949294949294949294949294949294949294949294313131D6D2CEFFFFFFD6D2CEFFFF
+FFD6D2CED6D2CE0896000896000896000896000896000896000896000896000896005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000000000
+000000FFFF00FFFF00000000000000FFFF00FFFF000000000000005265E60000000000005265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E600000000E70010920000B60000AA0000D700009E0000CE0000D20000D700009E0000CE0000A2
+0000D70000000000000000000000E70000CA000000000000000000000000005265E65265E6000000
+00000000D70000000000000000B200009E000000005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2
+CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2CE
+D6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+0000D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CE
+848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF000000D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000
+00949294949294949294949294949294949294949294949294949294949294949294949294313131
+D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008960008
+96000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000
+0000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF000000000000000000
+000000000000000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E600000000000000CE0000C60000B60000AE0000AE0000AE0000CA0000CE00
+009E0000000000000000000000000000000000AE0000000000BE0000BE0000B60000000000DF0000
+000000000000000000000000000000B60000000000000000A2000000000000005265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E60896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CE
+FFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE00000000000000000000
+0000000000000000000000D6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE
+D6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000D6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000000000000000000000000000000000
+00000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284
+424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00000000
+0000000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE00000094929494929400000094929494929494929494929494929494929494929494
+9294949294949294313131D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896
+000896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000052
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000
+00000000000000000000000000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000
+00000000B6000000000000000000000000000000000000000000000000005265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E60000000000000000000000000000000000005265E65265E6
+5265E65265E65265E65265E65265E65265E600000000000000000000DF0000AA0000CE0000CE0000
+B60000D70000DB0000000000000000B60000000000B20000CA0000A20000CE0000000000AE0000D2
+0000000000000000000000000000000000000000CA0000D700000000000000000000000000000000
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600089600089600D6D2CED6
+D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000D6D2CED6D2CED6D2CE84828442
+4142FFFFFFD6D2CED6D2CED6D2CE000000000000000000000000000000D6D2CED6D2CED6D2CE0000
+00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000
+D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000
+000000000000000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE00
+00000000000000000000000000000000009492949492940000009492949492940000009492949492
+94949294949294949294949294949294949294313131D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE
+0896000896000896000896000896000896000896000896000896005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000
+00000000FFFF00FFFF000000000000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E600000000000029860000A600089A00000000FFFF00FFFF00FFFF00FFFF00FF
+FF00FFFF00FFFF00FFFF0000000029860000AE0000D20000DB0000DB0000000000CE000000000000
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E6000000000000000000089A0000D70000
+C6000000005265E65265E65265E65265E65265E65265E600000000000000000000000000000000C2
+0000B60000AA0000D70000000000000000000000D70000DF0000B60000A20000DF0000B60000CA00
+00B60000000000000000000000000008960000BE0000BE0000000000000000D20000C20000D20000
+00000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142
+FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000D6D2CED6D2
+CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE
+D6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF
+FFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00000000000000
+0000000000000000000000000000000000000000000000000000000000000000000000000000D6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFF
+FFD6D2CED6D2CED6D2CE000000FFFFFFFFFFFF313131000000949294949294000000949294949294
+000000949294949294000000949294949294949294949294949294949294313131D6D2CEFFFFFFD6
+D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896000896005265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000000000000000000052
+65E65265E65265E65265E65265E65265E65265E60000000000003A7D00318200009E00000000FFFF
+00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000003A7D00218A00089A0000DB00109200
+0000000000000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E60000000000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000052
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000000000
+00089A0000AE0000D70000B2000000005265E65265E65265E65265E65265E6000000000000000000
+00000019BA4A00000000000000D700009E0000000000A20000A20000CE0000AA0000CE0000B20010
+920000BE0000C20000D200089A0000D70000000000CA0000CA0000D70000CA0000CA0000000000E3
+000000000000000000000000000000000000000000005265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E6089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6
+D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFF
+000000D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6
+D2CE000000D6D2CED6D2CED6D2CE0000000000000000000000000000000000000000000000000000
+00000000000000FFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFF00000000000000000000000000
+0000000000000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFF
+FFFFFF000000000000000000000000000000000000000000000000000000000000000000D6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2
+CE000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000FFFFFFFFFFFF00000094929494929400
+00000000009492940000009492949492940000009492949492949492949492949492940000000000
+00313131D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600
+0896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000
+000000000000000896000000005265E65265E65265E65265E65265E65265E600000000000000BA00
+298A00298600089A00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000031820031820029
+8600089A0010920000D20000B60000000000000000B2000000000000005265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E600000000000000000000000000BA000000005265E65265E65265E652
+65E65265E65265E65265E65265E65265E60000000000000000000000000000000000005265E60000
+005265E60000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E600000000000000D20008960000C60000AA0000AE000000000000005265E600000000000000
+000000000000000000000000E70000E30000E30000000000E70000000000D70000DF0000C6001092
+0000A60000DB0000DF0000B20000B20000BE0008960000CA0000D70000000000C20000C60000CA00
+009E0000D70000000000D20000DB0000CE00009E0000AE000000000000000000005265E65265E652
+65E65265E65265E65265E60000005265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E608960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE8482844241
+42D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000000000000000D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000D6D2CED6D2CED6D2CED6
+D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000
+000000D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000
+00000000000000000000000000000000000000000000D6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CED6D2CED6D2CE000000000000000000000000FFFFFFFFFFFF000000000000000000000000FF
+FFFF000000000000FFFFFFFFFFFF000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2
+CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000D6
+D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000FFFFFF0000
+00949294949294000000FFFFFFFFFFFF000000949294949294000000949294949294000000000000
+000000000000000000949294313131D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008
+96000896000896000896000896000896000896005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF00000000089A000000000000000000005265E65265E65265E65265E652
+65E65265E6000000000000109200298600199200000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+000000003A7D0042790042790829860000A20000DB0000B60000DB00000000089A00089A00000000
+0000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E600000000000008960000000000C2000000000000
+000000000000005265E65265E65265E65265E65265E65265E6000000109200000000218A00000000
+0000000000000000000000000000000000005265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E600000000000000D70000CA0000B60000A60000B6000000
+0000000000D20000000000000019BA4A00000019BA4A00E30000E30000E70000000000000000D200
+00AA0000CE00009E0010920000AE0000AA0000CA0000A20000DB0000DB0000CE0008960000000000
+000000B20000000000000000D70000000000000000D20000D20000DB00009E0000C60000A60000E3
+000000005265E65265E65265E65265E65265E60000000000000000000000005265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF000000D6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE000000FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2
+CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CED6D2CE000000000000000000000000FFFFFFFFFFFF0000000000
+00000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFF000000000000000000
+D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000000000D6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE
+D6D2CE000000FFFFFF000000949294000000FFFFFFFFFFFFFFFFFFFFFFFF00000000000094929494
+9294000000FFFFFFFFFFFFFFFFFFFFFFFF000000949294D6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2
+CED6D2CE0896000896000896000896000896000896000896000896000896005265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000FF
+FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000000000DB002986000000000000
+005265E65265E65265E65265E65265E65265E65265E6000000000000000000000000000000000000
+FFFF00FFFF000000000000003182003A7D00298600318200427900198E0000C60000A20000D20000
+000000B20000AE0000CE000000000000005265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000109200000000000000
+00000042790000000000000000C6000000005265E65265E65265E65265E65265E65265E600000000
+0000000000198E0000BE0000000000D70029860000AE0000D2000000005265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000000000DB0000CE00
+00C60000B20000000000000000000000000000000000000000E30000000000000000E30000E30000
+E70000000000E300009E0000A20000D70000DB00089A0000CE0000BE0000C600089A0000AA0000B6
+00089A0000A600000000000000000000FFFF00FFFF0000000000000000A600009E0000CA00009E00
+00C20000C600089A0000CA000000000000000000000000000000005265E600000000CE0000DB0000
+00005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482
+84424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000
+000000000000000000000000000000000000000000000000000000FFFFFF000000D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2
+CED6D2CED6D2CE000000000000000000000000000000000000000000000000000000000000000000
+FFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6
+D2CE000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284
+424142FFFFFFD6D2CED6D2CED6D2CED6D2CE00000000000000000000000000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000D6D2
+CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000000000FFFFFFFFFFFF
+FFFFFFFFFFFF000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000949294D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2
+CE000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000949294D6D2CED6D2CED6D2CE84828442
+4142FFFFFFD6D2CED6D2CED6D2CE000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294D6D2CED6D2CE
+FFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008960008960008
+96005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000
+00000000FFFF00FFFF00000000000000FFFF00FFFF00FFFF00FFFF00FFFF00000000000000298600
+00A60000000000CE00218A000000005265E65265E65265E65265E65265E65265E65265E600000000
+0000000000000000000000000000000000109200198E003A7D0000C60000B200198E003182004279
+0010920000A60000000008960000CE0000B20000AA000000005265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E60000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600
+000000000000000000000000BE00218A0000000000DF0000CE0000BE000000005265E65265E65265
+E65265E65265E65265E60000003A7D0000B200198E0000DB00000000218E00089600000000000000
+0000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000
+D20000DB0000000000000000000000B20000C20000000000E30000BE0000CA000000000000000000
+0000E30000E30000E70000DF0000000000CA0000AA0000DB00009E0000A20000C20000D20000A600
+00AE0000DF0000D200000000000000109600000000000000FFFF00FFFF00FFFF00FFFF00FFFF0000
+000000C20000C20000CA0000000000000000BA0000DF0000BE0000DF0000E70000CA000000000000
+000000000000000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E60896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFF
+D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+00D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CE000000D6D2CED6D2CE000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000D6D2CED6
+D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000000000000000000000D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE00
+0000000000FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000
+00000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000949294D6D2CED6D2CED6D2CE848284424142
+FFFFFFD6D2CED6D2CED6D2CE000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000949294D6D2
+CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000FFFFFFFFFFFF313131313131
+313131313131FFFFFFFFFFFF313131313131313131313131313131313131313131FFFFFFFFFFFF00
+0000949294D6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896
+000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00FFFF00FF
+FF00000000000000000000089A000000000000000000000000000000000000005265E65265E65265
+E65265E65265E65265E65265E600000000000000000000E70000AA00218A00218E0000CE0000BA00
+009E00218E002986003182003A7D0000000000B20000BE0000A20000CE0000B20000000000000052
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E60000000000000000000000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E6000000000000109200298600000000218E002986000000003A7D00009E00000000
+0000000000005265E65265E65265E65265E65265E6000000199200198E0042790000000000000029
+86002986003A7D0000000000BE000000005265E65265E65265E65265E65265E65265E65265E65265
+E65265E600000000000000D70000B20000AE00198E00198E0000000000000000000000E30000E700
+00E30000C20000E30000000000000000000000E30000E30000000000A60000BE0000B60000DB0000
+A60000A20010920010920000BA00000000000000FFFF00FFFF00000000000000FFFF000000000000
+00FFFF00FFFF00FFFF0000000000C200000000000000FFFF00FFFF0000000000000000D20000AE00
+00C60000C20000BA0000000000BA0000C20000000000D2000000000000005265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE84
+8284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6
+D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF
+FF000000D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000D6D2CED6D2CED6D2CE848284424142FFFF
+FFD6D2CED6D2CED6D2CED6D2CE000000000000000000FFFFFFFFFFFFFFFFFF000000000000000000
+000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000949294949294D6D2CED6
+D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE000000000000000000000000D6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000
+000000949294949294D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000FF
+FFFFFFFFFF313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFF000000949294D6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600
+0896000896000896000896000896000896000896005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000
+00FFFF00FFFF00000000000000009E0000000000000000A200198E00089A00109200000000000000
+0000000000005265E65265E65265E65265E65265E65265E60000005265E600000000000000C20000
+A60000000000E30000DB00218A00009E003A7D00298600318200000000089A0000AE0000C20000D7
+00009E0000B6000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E60000000000000000000000000000000000005265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E600000000000000000000000000CA0000CE0000000000000000000010
+9600198E00218A0000000000D7001092000000005265E65265E65265E65265E60000002986001092
+0042790000000000D70000AA003A7D0042790000000000D7000896000000000000005265E65265E6
+5265E65265E65265E65265E65265E600000000D70010920000A60000AA0029860029860029860010
+960000000000AE0000D70000D70000A60000E70000000000000000DF000000000000000000000000
+0000C20000C20000D20000BA0000BA00009E00218A00000000FFFF00FFFF00FFFF00FFFF00FFFF00
+FFFF00000000FFFF00FFFF00000000FFFF00FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00FF
+FF00FFFF0000000000DB0000CA0000CE00089A0000000000B60000DB0000BE0000D7000000000000
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFF00000000000000000000000000000000
+0000000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFF000000
+000000000000000000000000000000000000000000000000000000000000D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2
+CE000000D6D2CED6D2CE000000000000000000000000000000000000000000000000000000000000
+000000FFFFFFFFFFFF000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000000000000000000000
+00000000000000000000000000000000000000000000FFFFFFFFFFFF000000D6D2CED6D2CED6D2CE
+D6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000FFFFFFFF
+FFFF000000000000000000000000000000000000000000FFFFFFFFFFFF0000000000000000009492
+94949294D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+000000000000000000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE00000000000000
+0000000000000000000000949294949294D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2
+CED6D2CED6D2CE000000FFFFFFFFFFFF313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294D6D2CED6D2CEFFFFFFD6D2CEFF
+FFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896005265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF00000000000000000000000000009E00089A0031820000000000000000
+000000000000000000000000D2000000005265E65265E65265E65265E65265E65265E65265E65265
+E65265E6000000000000000000000000109200009E0000A60000A200000000000000000000089A00
+00BA0000CE0000A20000CE0000C6000000000000005265E60000000000000000005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E600000000000000000000000000E70000BE00
+00AA0000E3000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E600000000000000000000000000000000000000000000000000000000AE
+00089A003A7D0000DB00198E0000C20000000000E30000BA004A75080000005265E65265E65265E6
+5265E6000000009E00318200298600089A00000000089A00109200089A00109200000000089A0042
+79000000000000005265E65265E65265E65265E65265E65265E600000000BA0000D70000B2003A7D
+00218E003A7D0010920000AA00000000009E0000CA00089A0000D70000BA0000AA00000000000000
+00000000000000BA00000000009E0000B60000CE0000A60000B60000C600109200000000FFFF00FF
+FF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00000000FFFF00FFFF00FFFF00000000FFFF
+00FFFF00FFFF00FFFF00FFFF00FFFF0000000000C60000C20000D20000B60000000000B20000B600
+00A20000B20000D7000000005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E6089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6
+D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000
+000000949294D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000
+00000000000000000000000000000000949294D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000949294D6D2CED6D2CED6D2
+CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000
+0000000000000000D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE000000000000000000000000FFFFFF000000000000000000000000000000FFFFFF000000000000
+000000000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE0000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142FFFFFFD6D2CED6D2CED6D2CE000000FFFFFFFFFFFF313131313131313131313131FF
+FFFFFFFFFF313131313131313131313131313131313131313131FFFFFFFFFFFF000000949294D6D2
+CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600089600
+0896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000FF
+FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000000000000000000000000000CE
+00109200298600000000000000000000000000009E00089A000000000000005265E65265E6000000
+0000000000000000005265E65265E65265E65265E600000000CE0000A20000CE0000000000000000
+A600089A00089600218A00089A00089A0000A20000B60000DB0000BE000000000000000000000000
+000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000
+E70000D20000A60000AE0000DF0000DB0000DB000000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E600000000CE0000000000CA0000D700109200009E00
+00E30000000000000000C200009E00218A0042790008960029860000000000DB0000000052710800
+00005265E65265E65265E65265E600000000000031820019920000DB0000000000BE002986004A75
+08089A0000000000CA0042790000C6000000005265E65265E65265E65265E65265E6000000000000
+089A0000000000000000AA002986003A7D00109600089A0000000000B600089A0000D20000CA0008
+9A0000AE0000DF0000CA0000AE0000000000CA0000000000DB0000DB00009E0000B200009E0000B2
+00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00000000
+FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000B20000DF0000
+DB0000000000C60000DB0000B60000C2000000000000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E608960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2
+CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE000000FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000949294D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2
+CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294D6D2CED6D2CED6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000949294
+D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE000000D6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFF000000FFFFFFFFFFFF000000949294D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE94929400000000000000000000000000000000000000000000
+0000000000000000000000949294949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294000000000000000000
+000000000000000000000000000000000000000000000000949294949294949294D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000FFFFFFFFFFFF3131
+31FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000949294D6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008
+96000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000AA00000000
+00000000000000000000000000DF00218A00089A0000A60000000029860000C20000AA0000000000
+00000000000000000000000000000000000000005265E65265E65265E60000000000000000000000
+0000000000C600009E0000AE00109200198E00218A0000BA0000C60000AA0000A20000B600000000
+0000000000000000000000000000000000005265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E600000000D20000D20000AA0000DF0000DB0000BA0000AA000000000000005265E6
+5265E65265E65265E65265E65265E65265E65265E60000000000005265E600000000000000E70000
+C200089600089A0000AE0000E30000C20000000008960000A20008960029860031820000000000DF
+0000C2000000005271100000000000000000000000005265E65265E60000004A7508527508199200
+000000009E002986004A7508198E0000000000CA004279002986000000005265E65265E65265E652
+65E65265E600000000000000AE0000DF0000D700000000109200218A0000CA0000000000B200089A
+0000B60000C20000D20000C20000DB00009E0000B600009E0000000000AE0000CA0000000000CE00
+00A20000CE0000CE00089A00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000
+0000FFFF00FFFF00000000FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+0000000000AE0000D20000A20000000000D70000C60000B60000BA000000000000005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600D6D2CE
+D6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6
+D2CE000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294949294D6D2CED6D2CED6D2CED6D2CE848284
+424142FFFFFFD6D2CED6D2CED6D2CE00000000000000000000000000000000000000000000000000
+0000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294949294D6D2
+CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CE
+D6D2CE000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF
+FFFF000000949294949294D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE000000000000D6D2CE000000000000000000000000000000000000
+000000000000000000000000000000FFFFFFFFFFFF000000949294949294D6D2CED6D2CE84828442
+4142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE9492940000000000
+00000000000000000000000000000000949294949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE949294000000000000000000000000000000000000000000949294949294949294D6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE
+000000FFFFFFFFFFFF313131FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294D6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2
+CE0896000896000896000896000896000896000896000896005265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FF
+FF0000000000000000000000CE0000CA0000000000000010960031820042790029860000D7001096
+002986000000000000000000000000000000005265E6000000009E000000000000005265E65265E6
+00000000000000E70000DF0000D70000C20000CE0000A60000BE0010920010960010920000BE0000
+A20000DB0000000000D70000DB000000000000000000000000005265E60000000000000000005265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E600000000000000E70000B60000A60000D70000AE0000AE0000
+AE0000A6000000005265E65265E65265E65265E65265E65265E65265E65265E60000000000005265
+E600000000000000E30000B200109200198E0000B600089A00218A0000AE000000003A7D00109200
+218A0000000000DB00218A005275080000000000000000000000005265E60000005265E65265E600
+000000A6005A6D1029860000000000BA00298600427908198E0000000000A2002986004A750800A2
+0000000000000000000000000000000000000000000000DB0000DF0000B20000D700000000000000
+00000000000000000000D20000C60000C20000BE0000B60000AE0000D70000D70000D70000000000
+C20000000000B60000BA0000AA0000CE0000B60000C600089600000000FFFF00FFFF00FFFF00FFFF
+00FFFF00FFFF00000000FFFF00FFFF0000000000000000000000BA00000000FFFF00FFFF00FFFF00
+FFFF00FFFF00FFFF00000000089A0000AE00009E0000AA0000A20000000000B60000D70000C20000
+00005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294949294D6D2CED6D2CED6
+D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6
+D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFF000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142
+FFFFFFD6D2CED6D2CED6D2CE000000000000000000000000000000000000000000D6D2CED6D2CE00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294949294D6D2
+CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE949294949294949294949294949294949294949294D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294949294949294949294949294949294
+949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FF
+FFFFD6D2CED6D2CED6D2CE000000FFFFFFFFFFFF313131313131313131313131FFFFFFFFFFFF3131
+31313131313131313131313131313131313131FFFFFFFFFFFF000000949294D6D2CED6D2CEFFFFFF
+D6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896005265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000
+00FFFF00FFFF0000000000000008960000000029860010920000B200000000000000000000000000
+00D200298600427900198E0000BE0000000000000000000000000000000000000000000000BA0000
+AE000000005265E65265E65265E600000000CA0000B600000000089A00009E0000D20000CE0000A6
+00198E0000000000000000000000000000BE0000CE0000B60000000000C600089600000000000000
+00000000AA000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000D20000D20000BE
+0000CA0000BA0000D700009E0000D2000000000000005265E65265E65265E65265E65265E65265E6
+5265E65265E60000005265E65265E600000000AA0000BE0000BA0019920000AE0000D70031820000
+DB0000000000BA003A7D0029860000000000DB003A7D004279004A75080000000000005265E65265
+E60000000000005265E6000000000000089A00298600000000089600636D104A750800BA00000000
+00A60063691052750800A2003A7D00218A00218A0000E30000DF0000000000000000000000CA0000
+9E00009E0000A200000000000000FFFF00FFFF0000000000000000A20000AA0000B20000B60000C6
+0000B60000000000DB00089A0000000000000000BA0000A60000CE0000AA00009E0000A200000000
+FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF0000000000A600198E0000AE0000
+0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000089A0000BE0000BA0000CE0000BE0000B2
+0000000000D2000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E60896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CE
+D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000009492949492
+94D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFF
+FFD6D2CED6D2CED6D2CE000000000000000000000000000000D6D2CE000000FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000949294949294D6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000000000
+00D6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+949294949294D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFF
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000094
+9294D6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896
+000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E60000000000005265E600000000000000000000AA0010960008960000
+00002986000000000000000896003A7D0031820000AE00000000000000089A000000000000000000
+0000000000000000BE0000DF000000000000000000005265E65265E600000000D20000C600000000
+000000000000000000000000000000109600009E0000DB0000CE0000A20000A20000DB0000A60010
+920000CA000000000000000000000000000000000000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+00000000000000D20010920000CA0000D70000CE0000D70000B6000000000000005265E65265E652
+65E65265E65265E65265E65265E65265E65265E600000000000000000000BA0000A60000B200298A
+00198E0000B6004A79083A7D00009E000000005A7110298600000000000000000000000000000000
+0000000000000000000000005265E60000005265E65265E600000000DB0000DB0000000000BA0063
+6D1042790000A20000000000CE005A6D105A711008960000A20000D200318E9C19BA4A00E3000000
+0000000000000000000019920000AE00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000
+00B60000D70000DB0000CA00089A0000000000D200089A0000B20000000000DB0000AE0000AA0008
+9A00009E00109600109600000000000000FFFF00FFFF00000000000000FFFF0000000000000000A6
+0010920000BA00009E00109200000000000000FFFF00FFFF0000000000000031820000AA0000CA00
+00DB0000CA0000C60000CE000000000000000000005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE84828442
+4142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CE000000000000000000000000000000000000000000000000000000000000
+000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000000000000000000000000000000000
+00000000000000000000000000000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE000000000000000000D6D2CE00000000
+0000000000000000000000000000000000000000000000000000000000949294949294D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE000000D6D2CED6D2CE00000000000000000000000000000000000000000000000000
+0000000000000000949294949294D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE00000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000949294D6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600
+0896000896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000218E
+00218A0000B600298600000000109600109600009E0000B20000B20029860000D700000000000000
+009E0000000000000000000000000000A200089A0000CA0000CA000000000000000000005265E600
+000000000000B20000BE0000C60000BE0000A600109200009E00089A0000A20000CE00009E0000CA
+0000BE0000B20000CE000000000000000000000000000000000000005265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E600000000000000C20008960000CA0000D20000C60000CA0000D20000AE
+000000000000005265E65265E65265E65265E65265E65265E65265E65265E600000000D700000000
+089600218A00218E0000A20031820000D20000DB00218A0000DB00000000198E003A7D0000000000
+A2006369103182003182000000000000000000000000000000000000000000005265E65265E60000
+000000000000001092007365194A790800B200000000009E00736519298600218A00000000000000
+318E9C00E30000000000BE0000000000E70000000000DF0000B200000000FFFF00FFFF00FFFF00FF
+FF00FFFF00FFFF0000000008960000A20000A20000BA0000CE0000D200000000009E0000A2000000
+0000DB0000AE0010960010920008960000A2000896003A7D00198E00000000000000089600000000
+00000000BE0010920000A60000A200009E00009E00109200218A0000B200000000000000089A0010
+920000AE00109200089A0000CE0000B60000C200009E000000000000000000005265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE94929494929494929494929494929494
+9294949294949294949294949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE949294
+949294949294949294949294949294949294949294949294949294949294D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CE949294949294949294949294949294949294949294949294949294949294
+949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE9492949492949492949492
+94949294949294949294949294949294949294949294D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2
+CED6D2CED6D2CE949294949294949294949294949294949294949294949294949294949294949294
+949294949294949294949294949294949294949294949294D6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6
+D2CED6D2CE0896000896000896000896000896000896000896000896005265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000
+5265E65265E600000000000000000000BE00199200000000009E00218A00427D002986003182003A
+7D0000A20000BE0000D70000000000000000000000000000000000A20000BA00089A0000C6000000
+00000000000000000000000000000000089A0000AA00009E0000CA0000A600109200089A00009E00
+00AE00009E0000A20010960000BE0008960010960000000000000000000000000000000000000000
+00005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E600000000000000E70000CA0000AE0000C200
+00DB0000C20000C200009E000000000000005265E65265E65265E65265E60000000000005265E652
+65E600000000E300000000089600298600218A00218A0029860010960000A6004A79080896001992
+00000000000000218A003182006B69103A7D0052710800000000E70000C60000B20000CA00000000
+0000005265E600000000BA000000000000000000007365194A7908298A0000000000B2006369105A
+6D1000000000000000B60000000000E70000000000DF0000000000D70000000000BA00000000FFFF
+00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000AA0000CE0000A600009E0000CE00
+00000000000000D20000000000000000C60000A20000C60000CE0000C60000AA00218A0000000000
+A2003182001992002986003182004A7508218A0000A600009E0000BA00009E0000BA00218E001092
+0000A60000A60000BE00318200218A00009E0010920000DB0000C200009E00000000000000000000
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E6089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84
+8284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482
+84424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284
+424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600089600089600
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E60000000000000000000000005265E60000000000000000000000000000001992002986
+00218E00198E00089A003182003A7D002986003A7D00000000000000000000000000000000009E00
+00CE0000C60000000000000000000000000000000000000000000000CA0000DF0000BE0010960010
+960010920008960000BA0000AA0000B200009E0000A600198E00089A001096000000000000000000
+000000000000000000000000000000000000005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000
+BE0000C60010960000A20000CE0000D200009E0000B6000000000000000000005265E65265E65265
+E60000005265E65265E65265E65265E600000000DF0000D200109600089600427900318200427900
+3A7D00298600318200089A00089600089600218A007365196B6919636910218A0000000000E30000
+BE0000A6004A750800B6000000000000005265E60000000000000000000000000000004279004279
+0000000000A2003182000000003A7D0031820000B20000000000E70000000000E300000000000000
+00DB0000DF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000C60008
+9A0000A20000CE0000C60000000000CE0000000000AA00000000000000089A0000B20000B200089A
+0000A200109200000000089A00298600218A003A820031820029860000BA00089600218A0000AE00
+00BE00109600109600109200089A0000BA00198E00527108218E00198E00218E0000DB0000D20000
+E7000000000000005265E65265E65265E65265E65265E65265E65265E65265E60000000000000000
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E608960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFF
+FFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE84828442
+4142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE8482844241
+42FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008
+96000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E6000000000000198E0000A2000000000000005265E6000000000000
+00000000000010960008960000BE0000AA0010960029860042790029860000CE0000000008960000
+000000000000D200218A00089A0000A20000000000000000000000000000000000000000000000E7
+0000D20000AE0008960000B200089A0010960000B200199200198E00009E0000AA0000BE00089A00
+00D20000000000000000A60000CE0000B20000A600198E000000000000005265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E600000000DF0000AE0010920000AA0000B20000C200009E0000CE0000D200000000
+0000005265E65265E65265E65265E65265E65265E65265E65265E600000000000000DF0000D70000
+AE00089A004A7908318200636D1052710852710800AE004A7908427900636910427D005275081992
+0000000000CA0000D70019920010960029860000CE001092000000005265E65265E65265E6000000
+00000000CA0000000000000000B6000000000000005271087365194A750800BE0000000000E30008
+960000000000000000B60000000000AA0000C600000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+0000000010920010960000D200009E00009E00109200000000009E0000000000000000AA0000D200
+000000089A0000B20000CE000896000000000000000896003A7D003A7D00298600527508218A0010
+9200198E00009E00109200089A00089A00089A0000B20000BE0000BE00218A00218A001096001092
+00009E0000C60000C60000AE000000000000000000005265E65265E65265E65265E65265E6000000
+00000000D7001092000000005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE
+848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142
+FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FF
+FFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142FFFFFFD6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896
+000896000896000896000896000896000896000896005265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E60000000000003A7D0010960000D20000
+0000000000000000000000000000000000000000000000198E0000A6003A7D005271085275083A7D
+0000CE0000B200218A00198E0000000000AE0010920000AE0000D200000000000000009E0000CA00
+00000000000000000000000000C20010920000AE00109200089A00089A00198E0010920010920000
+DB0000D20000A20019920000A20000000000A600298600089600109600009E00198E000000000000
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E600000000000000C200109200009E0000D70000DB0008
+9A0000AA0000DB0000C2000000000000000000000000005265E65265E65265E65265E65265E65265
+E600000000E30000B20000AA0000C200089A0000DB0000B600009E000896005275085A7110736519
+218E00218A003A7D0031820000000000DF0000C6003A7D0073651931820000B60052750800000000
+00005265E65265E600000000000042790000A60000000000000000C600427900527508427D003A7D
+0008960000000000E30000BE0000000000E30000000000000000CE0000CE00000000FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF00000000109200089A0010960000D20010920010960000000000B20000
+A20000000000000000C600089A0000000000C60000B20000A60000AA00000000218E00218A004279
+00318200298600109600109200198E00198E00198E00109200198E0000BA00089A00109600198E00
+218A0010920010960000A60000D70000B60000C60000D2000000000000000000005265E65265E652
+65E600000000000000000000BE00198E00009E000000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFF
+FF848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+8284848284848284424142FFFFFF8482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284848284848284848284848284848284424142FFFFFF84828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284424142FFFFFF
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284424142FFFFFF848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+8284848284848284848284848284848284848284424142FFFFFF8482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284848284848284848284848284848284848284848284848284848284424142FFFFFF84
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284D6D2CEFFFFFFD6D2CE
+FFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000
+0000AA004279004A750800000000AE0000000000000000000000000000000000000000000000BE00
+3A7D001092004A75084A7508298600318200198E0000CE0000B60000AA00089600089A0000000000
+000000000000B600009E0000000000000000000000000000AE0000AE0008960000B200198E001092
+00198E00198E00089A0000CE0000AA0000AE0000AE0000AA00000000089600009E00089A00109200
+00BE000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000C6002986
+0000C60000DB0000DB0000CA0000C60000CE0000B600089A000000000000000000005265E65265E6
+5265E65265E65265E65265E600000000000000BE0010920000C2002986004279005A711052711029
+860052711000AE0000CE0008960000000000000000000000E30000E7001092006369105271104279
+00009E00089A0000A2000000000000005265E65265E6000000089A0029860000A20000000000D200
+00D200089A0042790031820000CE0000D20000000000DF0000000000E30000000000000010920000
+9E0000BE00000000000000FFFF00FFFF0000000000000000A20010920000B20000B20000B2001092
+0000000000AE0010960000AE0000000000A20010960000C60000000000B20000C60000C60000A600
+000000089A001992004279087365192986003A8200109200298600109200089A00089A0010920010
+9200218A001096003182003A7D0010960010960000C200009E0000C60000C6000000000000000000
+005265E65265E600000000000000DB0000000000000000BE003A7D000000000000005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E60896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE
+D6D2CE84828442414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+4142D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896
+000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E600000000000000000000000000B200009E0000AA0000000000000000B20000
+000000000000000000000000000000000000C200427900318200298600198E0010920000CE001092
+0000A20000A60000000000000000000000D20000000000000000000000E70000000000BA0000C600
+00CE0000A600109200109200218A00089A0010960000A60000D70000B60000AE0000000000B60000
+DB0000CE00198E001096000896000000000000000000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E600000000000000BA0000C200089A0000AA0000AA0000A60000CE0000CE0000000000B2003A
+7D000000000000005265E65265E65265E65265E65265E65265E600000000D70008960000DB0000D2
+0000AA0000D2003A7D00636D1073651900000000000000000000A20031820000000000000000E300
+1992007B65194A75084A790800A6004A7508009E000000000000005265E65265E600000000B20019
+8E00089A00000000198E00109200527108218A0008960000C60000000000000000AE000000000000
+0000000000000000DB0000C20000AE0010920000000000000000000000CA0000C60000AA0000AA00
+00A20010920000CE0000B200000000089A0000B20000A20000000000AA0000CE00009E0000000000
+B20000B20000C60000BE00000000109600218A002986006B6910318200427900318200318200009E
+0000BA0010960000BA00089A00218A003182003A7D00218A0008960010920000DB0000CA0000A200
+00D70019BA4A000000000000000000000000000000109600009E0000BA00089A0000000000000000
+00005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6
+D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600
+0896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E652
+65E60000005265E65265E65265E65265E65265E65265E6000000218A0000C200218E000000000000
+00089600000000109200218A00089A001092000000000000000000003182003A7D005A7110298600
+10960010920000B20000A60000D70000D70000000000000000A200009E0000000000000000000000
+BE0000000000AE0000A200009E00009E00009E00218A0008960010960019920010920000BE0000DF
+0000BE0000000000CE0000B20000BE0010920010960000AA00218A000000000000005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E600000000E70000B200089A0008960000AE0000CE0000D20000DB
+0000000000000000CA00089A003A7D000000005265E65265E65265E65265E65265E65265E6000000
+009E00427900318200199200009E003A7D003182003A7D000000004A75083A7D0052710800000000
+0000FFFF00FFFF00000000000000636D107365192986004279005275083182000000000000005265
+E65265E60000000000000000000000000000003A7D00198E0031820052711031820000C600000000
+00DF00089A0000000000000000D20000AA0000D70000000000000000D20000000000CE0000B20000
+9E00318200318200089A00089A0000B600089A0000B20000000000DB0000BA00000000009E0000C2
+0000B200089A00000000109600089600109600089A00000000109200218A00298A003A7D004A7508
+3A7D00089A00218A00218A00218A00089A00089600109200109600218A00109200089A0000A60000
+A60000C20000B20000C60000E30000000000000000000000000000A200089A0031820010960000B6
+0000B60029860000E3000000000000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008
+9600089600089600089600089600089600089600089600089600089600089600089600089600D6D2
+CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6
+D2CE0896000896000896000896000896000896000896000896005265E65265E65265E65265E65265
+E65265E65265E65265E60000000000000000000000005265E65265E65265E65265E6000000000000
+000000000000198E0000CE00089600198E00000000199200198E003A7D003A7D00218A003A7D0000
+A600198E00318200318200089600198E0008960000C60000AA00089A00000000000000009E000000
+0000000000000000B20000000000000000AA0000AA0000C200109600109600198E0010960000BE00
+009E00009E0000B60000C60000000000CE0000D20000B600009E0010960000A20000CA0000000000
+00005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000009E0000BA00000000
+00000000000000000000000000000000000000D2002986004279000000005265E65265E65265E652
+65E65265E65265E600000000000000BE003A7D005271083182002986004A75087B65190000005A71
+107B6D21000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000005A71107B651900A600527108
+089A000000000000000000005265E60000001092000896000000000000004A750842790031820010
+960019920000CE0000000000E30010960000E70000000000B600089A0000C2000000000000000000
+0000B20000A20000C20000BE00298600198E00089A0010960008960029860000A60000000000BA00
+00000000000000AE0000C20000A200089A00000000109600089A00009E0000000000B200009E0019
+8E00218A004A7908318200318200298600218A00198E00089A00198E00198E00089A0000A60000AA
+0000CA0000C60000CE0000AA0000DF0000B60000DB0000000000000000E30000000000B600427D00
+4A75084A750800A200009E004A7508009E0000DF00000000318E9C0000000000005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E6089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442
+41428482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+8284848284848284848284848284848284848284848284848284848284848284FFFFFFD6D2CEFFFF
+FFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E600000000000000AE000000000000005265E652
+65E65265E65265E600000000000000000000000000CA0031820000000000B2003A7D002986001092
+0000000000000000000000BE000896003182003A7D0010960029860000BA0000C600089A0000CA00
+00000000A60000000000000000000000000000CA0000000000000000000000A60000BE0010920010
+920008960000A60000A60000AA0000CE0000DB0000AA0000000000B20000D20000D20000A20000DB
+0000A20000D7000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000
+000000000000000000000000DB00009E00000000000000FFFF00FFFF000000000000004279000000
+000000005265E65265E65265E65265E65265E600000000000000D20000A2003A7D00198E00427900
+298600089A000000007B6519427900000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000073
+6519427900198E006B691010920000000000E30000000000000000000000AE0000BA000000000000
+00198E004A75085275083A7D0029860000BA0000000000CE0000C20000B60000000000C20000B600
+00C20000000000DB0000A20000B60000AA0000CE0000C600089A00089A00109600198E0029860031
+8200218A0000000000000000000000A60000A20000AA0000BA0000B200000000089A0010960000C2
+0000000000AE00009E00199200000000000000000000000000000000000000000000218E00218A00
+109600009E0000000000000000B20000C20000DF00089A0000000000000000000000000000E30000
+000000C20000C6004A75084A75083A7D0000BE00009E0042790000A60000000019BA4A00E300318E
+9C0000000000000000005265E65265E65265E65265E65265E60000005265E65265E65265E65265E6
+5265E65265E65265E65265E65265E608960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2
+CED6D2CED6D2CE848284424142848284424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+D6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008
+96000896005265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000000000
+00009E00198E000000000000005265E65265E65265E65265E65265E6000000000000000000000000
+000000000000000000000000000000000000000000089A00198E003A820042790842790029860008
+9600089A0000CE0000DB0000A20000000000000000BA00009E00000000009E0000D7000000000000
+0000C600009E00089600089600009E00009E0000A20000BE0010920000D20008960000000000B200
+089A0000E3000000000000000000000000000000005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E6000000000000009E0010920000CE0000BE00000000FFFF00FFFF00FFFF00FFFF00
+FFFF00FFFF000000000000000000005265E65265E65265E65265E600000000000000000000000000
+000000000000C20000000000000000000000B20000C600000000FFFF00FFFF00FFFF00FFFF00FFFF
+00FFFF00FFFF00FFFF000000007B651900B2005A6D1000B60000000000DF000000005265E6000000
+00A60010920000000000000000D7001092003A7D004A7508218A0000BA0000000000DB0000CA0000
+000000000000CE0000BA0000D20000000000DB00009E0000BA00009E0000CE00109200218A00089A
+00089A00198E00298600198E00198E0000000000CE0000000000AE0000BA0000CE0000BA0000B200
+00000000B200009E0000000000A200089A001092000000000000002986003A7D0031820029860021
+8E00218A00000000000000000000000000FFFF00FFFF0000000000000000000000000000C2000000
+0000000000000000000000C20000B600298A00527110427900009E0008960052710829860000E700
+00000019BA4A00E300318E9C000000318E9C00D2000000000000005265E65265E65265E600000000
+00005265E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284
+424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896
+000896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E6000000000000089A000000000000000000000000000000005265E65265E65265E652
+65E600000000000000000000000000000000000000000000000000000000DB0000B2001992002986
+0031820029860029860019920000BA0008960000D20000BA0000AE0000000000BE0000B600000000
+00C60000B20000000000000000000000000000A20000A600009E00009E00089A0000B60000000000
+000000000000000000000000B60000BA000000000000000000000000005265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E6000000089A00009E0000AE00000000000000FF
+FF00FFFF00FFFF00FFFF00FFFF00FFFF00000000089A000000005265E60000000000005265E60000
+0000000000A600000000000000000000000000089A00089A00089A00198E0000AA00000000FFFF00
+FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000003A7D00009E0000B20000000000000000
+000000000000000000000000000000000000000000000000000000000000C60000A600198E001096
+0000000000BA0000000000000000B60000000000CE0000DB00009E0000000000DF0000B60000A200
+109600109200009E00089A00009E00089A00298600218A0000000008960000000010960000AA0000
+DB0000AA0000A20000A60000BA00000000000000000000000000089A00000000218E00198E003182
+00427D003A7D003182003A7D00318200109600000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+00000000000000000000DB0000000000000000000000D2000896004A75087B65196B69192986004A
+7508527108089A0000AA0000000000E30019BA4A000000000000318E9C00E30000D7005265E60000
+0000000000000000C20000AE000000005265E65265E65265E65265E65265E65265E65265E6089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241428482844241
+42FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFF
+D6D2CED6D2CE0896000896000896000896000896000896000896005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E6000000000000000000000000089A0000DB0000DF000000
+000000005265E65265E65265E65265E6000000000000000000000000000000000000000000000000
+00AA0000B200218A00298600218A003A7D00218A003A7D00198E00198E0000AE0000A60000000019
+8E0010960000000000CE0008960000C60000A20000B20000000000BE000000000000000000000000
+0000000000000000BA0000000000BA0000000000000000D70000CE0000D20000C200000000000000
+0000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000BA0000D2
+00000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000000000000000
+00000000000000000000000000000000CA00009E00089A0000BA00000000000000427D004279003A
+82003A7D00109200000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000006B69103A7D0000A6
+0000E300000000009E0000000000000000000000000000A200198E00000000089A00009E0000C600
+00000000000000000000000000E70000B60000000000CA0000AA0000000000A20000D70000DB0000
+000000000000DB0000BE00109600109600089A0000BE00218E0000AA00218A0010960000000000A6
+0000000000C60000B20000DF0000AA0000BA0000A20000A20000B200000000000000000000000000
+109200109600198E001092003182003A7D00298600298600218E00318200000000FFFF00FFFF00FF
+FF00FFFF00FFFF00FFFF00000000009E0000000000000000000000000000000000AE00198E005A71
+107B69215A71103182004A75084A750800DB0000000000000000E70000E300000000318E9C000000
+00000000E30000E300318E9C0000000000000000000000000000000000005265E65265E65265E652
+65E65265E65265E60896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE
+848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6
+D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896005265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000BA00000000
+00B20029860000C60000C6000000000000000000005265E600000000000000DB0000BA0000C60000
+D70000AA00009E0000000000A20000BE00089600218A00218A00199200218A00109200089600218E
+00109600109600000000198E00198E0000000000D20000A600009E0000C600109200000000089600
+00B20000C60000D70000AE0000CA0000000010920000000000000000000000000000000000C60000
+B20000DB0000AE000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E6000000000000000000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+FF00000000000000318E9C318E9C00CA0000000000000000E70000CA003A8200198E001092002986
+000000002986007365196369107B69194A7508000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+0000004A7508218A0000A60000000000CE0000AA0000DB0000000000000000000000000031820019
+920000000000000029860010920000A60000000000000000000000000000000000AA0000B6000000
+0000D20000CA0000B200009E0000CE0000000000000000AA0000C60000C60008960000A60000CE00
+089A00000000009E0000C60000000000000000000000000000000000DB0000A20000DB0000DF0000
+0000000000000000089600218E00198E004279001096004279004279002986004A7508218A000000
+00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000000000BA0000C200000000
+000000009E001992002986007365195271103A7D004A750831820000BA0000000000000000DF0000
+000000E30000E300318E9C000000000000000000000000009E0000CA0000DF000000000000000000
+005265E60000000000005265E65265E65265E65265E6089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFF
+FFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600
+0896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E600000000000000AE00000000218A00198E00089600009E0000AA000000000000005265E60000
+00000000000000198E0000A600000000000000000000089600198E00218E00109600009E00109200
+00BA00109200109200198E0010920000000000C200109600109200000000089600218A0010920021
+8A00109200000000009E00009E0000A60000A20000C60000000000AA0000A20000B20000B6000000
+0000000000000000000000C20000BA0000DB000000005265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E600000000000000D70000C600000000000000FFFF00FFFF00FFFF
+00FFFF00FFFF00FFFF00000000089A0000D700000000318E9C00DF0000DF0000000000DF0000C600
+009E005A6D10427D0000000000000000CE00089A007B69197B71214A7508636910000000000000FF
+FF00FFFF0000000000000010960000A60000AE0000000000D700089A0031820000A60010960000E7
+00000000000000218E0010960000BE00000000298600218A004A7908298600089A00000000000000
+00DB0000A20000CE0000000000000000D70000D70000BA00009E0000AE00009E0000000000000000
+000000A60000000000000000000000000000000000000000AE0000B20000B20000B60000A2000000
+00000000000000000000009E0000000000C60000A600218A00427900218A002986003182003A7D00
+298600318200198E00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000
+0000089A0000AE0000000000BE000000004279004279007B65195A6D10527108009E0010960000AE
+0000000000E30000DF00000000318E9C00DF00318E9C318E9C318E9C00DF0000CA0000A20000DB00
+00D200009E0000C2000000000000000000000000005265E65265E65265E65265E608960008960008
+9600089600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2
+CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF
+FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08
+96000896000896000896000896000896000896005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E600000000000000DB0000D20000B600009E00109600000000
+0000000000005265E65265E6000000000000000000000000000000000000089A00009E00218A0000
+9E00198E00109200218A0000B60000CA0000C60000AE0000A60000000000CE0000BE000000000000
+00218A002986003A7D00318200089A0000A20000000000AE0000A600009E0000000000A200109200
+00BE00009E0000C6000000000000005265E60000000000000000000000005265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000
+000000005265E65265E65265E65265E65265E65265E600000000000000000000DB00089A00009E00
+000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000298600089600000000318E9C00E30000
+DF0000E30000000000B6004A7508298A004279005A711000000000BA005A6D103182007365197B6D
+217365197B65197365190000000000005A711000BE0000C600000000000000000000198E004A7508
+636D10009E0000C20000A60000000000000000BE0031820000C60000C60000000042790052750831
+8200218A0000CE0000000000000000DF0000B60000D70000AE0000000000D200089A00009E0000DB
+0000B20000000000DB0000DB0000000000000000A20000B60000A60000B20000AE0000AE0000AE00
+00CE0000A20000A20000AE0000AE0000000000C60000AA0000D200000000089A0019920042790008
+9A003A7D004279003182004A75083A7D00198E00198E00000000FFFF00FFFF00FFFF00FFFF00FFFF
+00FFFF0000000000000000D700009E00089A0000BE00109200000000427908527110736519527110
+318200089A0000DB00089A0000000000DF0000CA0000000000DF0000E30000E30000DF0000E70000
+D20000D20008960000C60000A200218A0000AE0000000000000000C2000000000000000000005265
+E65265E6089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442414284
+8284424142FFFFFFFFFFFFFFFFFFFFFFFF848284848284848284848284848284848284848284FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2
+CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896005265E65265E65265E6
+5265E65265E60000000000005265E65265E65265E600000000000000000000000000000000000000
+C60000000000000000B20000D700089A000000005265E65265E6000000000000000000089A000000
+0010920000B20000CA0000A200009E00089A0010960010920000C60000DB0000B200009E00000000
+00BE0000B600000000218E0000B600218A004A75083A7D0000AE0000BA0000A200000000089A0000
+9E00000000109200089A0000B2000000000000000000000000005265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E60000000000000000005265E65265E65265E65265E65265E65265E65265E600000000
+000000D700109200089A0000D700000000000000FFFF00FFFF0000000000000000D20000BA004279
+0000000000E30000E30000E30000E70000000000C2003A7D005271087B691952750800000000A200
+5271087B69197B71217365197B69197B6519636D105A6D10089A00009E0010920000000000C60000
+000000BE004A75087B75217B6D2100BE0000C60000DB0000000000000000C200218A0000C20000C6
+000000004A79085275083A7D003A7D0000AA00000000000000089A0000DB0000A20000AA00000000
+000000009E00009E0000DF0000000000000000B20000000000DB0000A20000DF0000B60000A60000
+AE0000B20000CE0000AE0000A60000AE0000DF0000AA0000A60000000010960000CE0000CE000000
+0000B200109600198E00218A003A7D00198E00318200218A004279003A7D00109200000000FFFF00
+FFFF00FFFF00FFFF00FFFF00FFFF0000000000CA0010960000A20000CE00109200089A000000004A
+75084A75085A6D10527108298600089A0000DB0000D70000000000CA0000BE0000000000DF0000DF
+0019BA4A00E30000E30000D70000AE0000A60000A6004A750800CE0000A60000000000DB00000000
+00000000C6000000005265E65265E608960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2
+CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFF000000000000FFFFFF000000FFFFFFFFFFFFFF
+FFFF000000FFFFFF000000000000FFFFFFFFFFFF000000000000000000FFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000
+FFFFFFFFFFFF000000FFFFFF000000000000FFFFFFFFFFFFFFFFFF000000000000000000000000FF
+FFFF000000000000000000FFFFFF000000000000FFFFFFFFFFFFFFFFFF000000000000000000FFFF
+FFFFFFFF000000000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000000000
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CE
+FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008
+96005265E65265E65265E65265E60000000000000000000000005265E65265E600000000C20000BA
+0000000000000000000000000000B60000D200218A00089600000000000000000000000000000000
+00000000D70000000000000010960000C60000C600198E0000A20000000000000000000000000000
+CE0000B200089A0000000000000000000000AA0010920000A200198E003A7D0010920000C60000AA
+0000A60000D700000000000000089A0000BE0000000000000000CE0000D700000000000000000000
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E600000000000000CA000000005265E65265E65265E65265E65265
+E65265E600000000000000000000000000000042790000A600000000089600000000000000000000
+198E0000BA003A7D0010960000C60000000000000019BA4A00000000E30000CA0000000000000073
+65195275085A7110000000000000318200636910636D107B75217365197B71216B69104A75083182
+0000000000D70000B6000000003182006B691063691073651900B200089A0000BE00000000000000
+00A600318200427D00089A00000000000000427900427D004A750810920000A60000000010920000
+A20000A20000DB0000DB0000000000000000BE0000000000DF0000DF0000DB00000000009E0000B6
+0000A60000BA0000A20000AE0000B20010920000A20000B200089A0000AE0000AE0000CE00000000
+10960010960000D20000C60000000000BA00218E003A7D00218A00318200298600298A0042790021
+8A00199200318200000000000000FFFF00FFFF0000000000000000A600009E00009E0000BA00009E
+00109200298A002986000000004279005A7110427908089600218A0000C60000000000DF0000CA00
+00BA0000000000000000000000000000000000BA0000D70000CE003A7D0000A6003A7D0010960000
+C200000000218E0010960000000000C6000000005265E65265E60896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142
+D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF84
+8284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFF000000FFFFFFFFFF
+FF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFF000000FFFFFF000000000000FFFFFFFFFFFF000000FFFFFF000000FFFF
+FFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFF
+FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896
+000896000896000896000896005265E65265E65265E600000000000000AA0000D200000000000000
+5265E60000005265E600D20000D200000000000000000000009E0000B200089A0000C60000000000
+000000000000000000000000000000BA00198E0010960000000000CE0000B60000C6000000000000
+0000000000000000000000000000000000000000000000000000000000000000BE00198E00109600
+218A00009E0010920000DB0000BE0000AE00000000009E00009E00198E0000000010960000A20000
+DB000000000000000000000000000000000000000000000000005265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E600000000000000CA0000D7000000005265E6
+5265E65265E65265E65265E65265E600000000000000000000E70000000029860000BE0000000000
+0000318200000000000000089600198E003A7D00198E0000B20000BE00000000318E9C0000000000
+00000000FFFF00FFFF000000000000007365191092007369190000006369107B6D217B7121527110
+4A750831820042790000000000D70000B2000000006B69195275086B69195A6D101096003A7D0029
+860000A20000000000000000BE00199200318200298600198E0000D7000000005271083A7D002986
+00009E00000000000000009E00009E0000A20000A60000DB0000CE0000000000000000DF0000DF00
+00DF00000000009E0000AA0000B20000DB0000AE0000AE00009E0000AA0010920000C20010920000
+CA0000AE0000CE00009E0000000000AE0000C600009E00000000000000218E00218A00089600218A
+003182001992003A7D00109600089600089A003A7D0000000000000000000000BE0000A60000A600
+00A20000A20000AE00198E001992002986002986000000003182004A7908318200298A0029860000
+CA0000000000DF0000CA0000C20000E70000BE0000E70000DF0000000000DB000000000000000000
+000000000000000000000000000000001092000000000000000000005265E65265E65265E6089600
+089600089600089600089600089600089600089600089600089600089600089600089600089600D6
+D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFF
+FFFFFFFFFFFFFFFFFFFF848284000000000000000000000000000000848284FFFFFF848284FFFFFF
+848284FFFFFF848284FFFFFF848284FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000
+FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFF
+FFFF000000000000000000000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFF000000FFFFFFFFFFFFFFFFFF
+000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFF
+FFFF000000FFFFFFFFFFFF000000000000000000000000FFFFFF000000FFFFFFFFFFFF0000000000
+00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CE
+D6D2CE0896000896000896000896000896000896000896005265E65265E65265E600000000000000
+B200089A0000BE000000000000005265E600000000000000000000CE0000000000000000000000B2
+0000D20000B200000000000000009E0019920000000000AE0000D20010920000CE0000000000B200
+00E30000000000A20000000000000000000000000000000000000000000000000000000000000000
+000000D20019920000BA00009E0000A20000C200109600089A0000000000000008960000A6000000
+0008960008960000B20000000000000000A20000B60000B60000BA0000CE0000AA000000005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000010960000000000
+D700089A000000005265E65265E65265E65265E65265E65265E600000000CA0000E3000000000000
+00000000218A003182000000000000000000003A7D001992004A7508198E003A7D0000CA0000BE00
+000000318E9C000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000636D1063691029860000
+00000000000000006B69107B6D215A6D104A75080000003A7D000000000000007365197B69217369
+197B6519218A00527108218A00009E0000000000000000DB0000DB00298600298600218A0000D700
+0000003A7D004A7508298600009E0000000000000000A60000B60000AE0000C20000AE0000AA0000
+000000BE0000000000000000000000000000B20000A20000AA00089A0000A600109200298A00089A
+0000BE0000C20000BE00009E0000BE0000AA0000C60000B200000000109600198E00218A00000000
+009E00427908218A00218E00218A00218A002986004A7908298A00000000000000000000198E0000
+A20000BA0000BA0000B200109200298600198E00218A00198E00298600298600298A000000000000
+0000000029860010920000CE0000000000CA00089A0000E30000CA0000E70000CE0000E700000000
+000000000000198E005A6D10198E0000DF0000D70008960000000000000000AA00089A0000000000
+00005265E65265E60896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284
+424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84
+8284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF
+FFFF000000FFFFFF000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFF
+FF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF00
+0000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFF
+FFFFFFFF000000FFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000
+FFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFF
+FFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896005265E65265
+E65265E600000000000000000000000000000000BA00000000000000000000000000000000000000
+00BE0000000000C20000000000000000D20000AE00009E00000000089A0000D200000000218A0010
+960000A60000000000000000000000AE0000B2000000000000000000005265E60000000000000000
+0000000000000000000000000000A60000C20000A20000A60000A60000CE0000C200000000000000
+00000000DB0000000000BE00218E0000AE0000000000000000C600218A00089A0000B60000DF0000
+C2000000000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E60000
+00009E0000AE00000000009E0000DB00000000000000000000000000000000000000000000000000
+00E70000BA0000000010920000000000B6003A7D00089A0000A60000B200318200009E0029860008
+9A004A7908089A0000AA0000000000E300000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000
+007B6919736519527108736519736519000000527108109200218A00000000000000198E00000000
+0000004A75087B71217B71215A6D105A71107B7521089A000000000000000000003A7D0000CE0019
+8E003A7D00298600198E0000C6000000003A7D0000000000000000000000000000A20000AE0000A2
+0000A20000CE0000000000000000DB0010920000DB0000000000000000BE0000D20000C600009E00
+00B200109600109200009E0000AA0000AA0010960010960000C20010960000B20000C60000000000
+B2003182001096000000000896004A7908089A00199200318200318200427900736519000000009E
+0000BA0000A60000C20010920010920019920000BA00218A002986003A7D003A7D00218A00298600
+2986003182003A7D0029860029860000000000000000000000000000CA0000D70000DB0000CA0000
+CA0000E70000BE0000000000AA0000AA00218E00218A00198E0000A600198E0000BA0000C60000BE
+0000000010960000D7000000005265E65265E6089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6
+D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FF000000FFFFFFFFFFFF000000000000FFFFFF000000FFFFFF000000FFFFFFFFFFFF000000FFFFFF
+FFFFFF000000000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF00
+0000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF
+FFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF
+000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFF
+FFFF000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF
+FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600
+0896000896005265E600000000000000000000000000D70000A20000AA0000A20000D70000B20000
+000000DF0000000000000000000000000000A20000BA00089A000000001092001096000000000000
+0000AA0000000000BA00009E0000D70000000000000008960000CE000000000000000000005265E6
+00000000D70000000000000000000000000000000000000000000000DF0000B60000BE0000000000
+A20000000000000000D70000CE0000D20000000008960000C20000000000A20000000000B20000DB
+00089A0000A20000CE0000000000000000000000B6000000005265E65265E65265E65265E65265E6
+5265E65265E600000000BA00009E0000B60000000000BE0000000000000000000000000000000000
+000000000000000000000000B60000B60000AE00000000089A00000000000000218E0031820000AE
+0000A200199200198E00109600318200218A0000B20000DF00000000FFFF00FFFF00FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF000000007369196369100000000000007B6D2100000000000000000000
+00004279002986000000000000005271087365197B69216B69107B7921736519198E000000000000
+000896004279003A7D00009E004279004A790842790000C600000000000000FFFF00FFFF00000000
+00000000DB0000000000000000000000000000C60000B20000A200089A00109200109200009E0008
+9A0000A200109200089A00199200218E00218E00198E00199200089A0000A60010920000A60000A2
+0000C60000BE0000000000D2003182001092003A7D00000000000000218E00199200089A00318200
+2986004A7508000000218A00089A0000AA00089A0000A600109200089600198E00198E003A820042
+7900218A00298600298A00298600298600298600298600089A00089A0000DB0000C20000000000DB
+0000C20000D20000C20000E30000DF0000000008960000A60000AE0000B200089A0000A2004A7508
+198E003A7D00198E00198E0000B6000000000000005265E65265E65265E608960008960008960008
+9600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE8482
+84424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFF
+FFFFFF848284848284848284848284848284848284848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000
+000000000000FFFFFFFFFFFFFFFFFF000000000000FFFFFF000000FFFFFF000000FFFFFFFFFFFF00
+0000FFFFFFFFFFFF000000000000FFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF0000000000
+00000000000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000
+FFFFFFFFFFFF000000000000000000000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFF
+FFFF000000000000000000000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF
+FFFFFFFF000000000000000000000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF
+000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008
+960008960008960008960008960008960000000000000000000000DB0000B60000CE0000AA000000
+00000000000000000000000000009E0000000000000000000000000000000000CE00109600089A00
+000000009E0000AE0000D20000000000A2000000000000000000005265E600000000000000000000
+00005265E65265E600000000000000C6000000000000000000000000000000000000000000000000
+0000000000000000000000BA0000000000000000000000D70000000000D700009E00000000009E00
+00000000A20000A60000CE0000CA0000AA0000000000000000000000D70000C2000000005265E652
+65E65265E65265E65265E65265E65265E600000000D70031820000C200000000089A000000000000
+0000000000000000000000000000000000000000000000AE00009E0000CA0000000000000000DB00
+00CE0000000000000031820000AA0000AA00109600089A0000A20000A60000A600009E00000000FF
+FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000000000000000FFFF00FFFF000000
+00000000089A005A71107B65194279081992000000000000007365197B69197B7521636910636910
+5A6D1000DB0000000000000000CA00009E006B691031820000AA00427908089A00000000FFFF00FF
+FF00FFFF00FFFF00FFFF00FFFF0000000000000000AE00089A0000AA0000B20000D200009E0000DB
+0000DB00089A0000DB0000DB0000B200089A003A82003A7D00218A003A7D00218A00198E00218A00
+089A00009E0010960000A60000BE0000C200000000109600089A0000BE00198E0000000029860008
+9A00218A00198E00298600000000000000218A0000B600009E0000A600009E0000A600109600198E
+00218A003A7D003A7D005A7110298600298600298600298600298A003A7D0010960000A60000B200
+00B60000000000AE0000000000CE0000BE0000C60000DF0000DF0000000000CA0000BE001092004A
+75084279003A7D0052750829860000AA00009E0008960000AE000000000000005265E65265E65265
+E65265E6089600089600089600089600089600089600089600089600089600089600089600089600
+089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442414284828442
+4142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFF
+FFD6D2CED6D2CE08960008960008960008960008960008960000000000CA0000CE0000B200000000
+000000000000000000000000009E0000CE0000BE0000000000000000000000000000000000000000
+000000000008960000AE00009E0000000000000000000000000000000000000000CA000000000000
+005265E65265E60000005265E65265E65265E6000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000010920000B20000000000BE00089A00089A0000C60000000000C60000000000B60000D7
+0000CA000000005265E65265E65265E65265E65265E65265E65265E600000000A20019920000A200
+00000010960000000000000000000000000000000000000000000000000000000000000000000000
+000000CA0000CA0000000000C20000D200000000000000218A00009E0000AA001092000896001096
+0000A600000000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000000000FFFF00
+FFFF00FFFF00FFFF00FFFF00FFFF000000003A7D007B6D217365190000000000007B691900000000
+00005275086B691952710829860000000000000000000000D2003182007365194A7508198E002986
+003A7D00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000B200009E0000B20000A200
+00B20000A60000DB0000CE00009E0000D70000AA0000D20000C6003182003A7D004279002986003A
+7D00298600218A0010960010920010920000BA0000AA0000B20000C60000000000C20000AE0000AE
+0000A600009E0000000000AE001092000000000000001096003A7D00198E00109600089A0000A200
+08960000B600089A00218A00198E003182004A7508427908318200298600298600298600218A0021
+8A00218A00009E0000CE0000C60000000010960000000000000000C20000D20000E30000DF000000
+0000DB00009E00198E002986004A7908218A0000AA00009E0000C600089A00000000000000000000
+0000005265E65265E65265E65265E608960008960008960008960008960008960008960008960008
+9600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2
+CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFF
+D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960000000000
+00000000000000000000000000000000005265E600000000000000000000000000A60000000000BA
+0000B20000D20000000000000000000000000000AE00198E0000D20000BE00000000000000000000
+009E0000AA000000000000005265E65265E65265E65265E65265E65265E60000005265E600000000
+00000000000000005265E65265E60000000000000000005265E60000000000000000000000000000
+00000000000000000000000000198E00089A00000000009E00009E00218A0000A600009E00000000
+009E0000000000D70000B6000000000000005265E65265E65265E65265E65265E65265E600000000
+000000B200199200089A0000A60000000000B6000000000000000000005265E60000000000000000
+00000000218A0000C20008960000000000000000C20000000000000000D700000000000000000000
+08960010960000000000000000000000B200089A00000000FFFF00FFFF00FFFF00FFFF00FFFF00FF
+FF00000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000007B6D21636D10000000218A
+00000000000000FFFF00FFFF00000000000000000000000000000000000000089A0000AE007B6519
+6B69195271083182004A7508000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000
+000000B20000CA0000B60000AA0000AE0000B20000AE00009E0000DB0000A2000896003182002986
+00218A00218A003A7D003A7D00298600318200089600198E0008960010920010960000B20000A600
+00000000AE00089A0010960000B20000B20000000000A6000000003182003A7D00198E0031820021
+8A00298600218A0010920000A200089A0000B600089A00198E002986004A7508427D00298600218A
+00198E00089A00198E00198E0000B200089A0000D200000000089A0000AA00009E0000000000CA00
+00DF0000DF0000DF0000000000D70000A200089A003A7D003A7D0073651900C20000B60000E30000
+00000000000000000000005265E65265E65265E65265E65265E60896000896000896000896000896
+00089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CE
+FFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896
+000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+000000000000000000089A0000000000000000000000DB0000D70000000000AE0000000000000000
+00000000000000000000000000000000000000005265E65265E65265E65265E65265E65265E65265
+E65265E65265E60000000000005265E65265E65265E65265E60000000000005265E6000000000000
+000000009E0000C200000000000000000000000000000000009E0000000000000000A600198E0010
+960000B20000000000A60000A200009E0000000000DB000000000000005265E65265E65265E65265
+E65265E65265E600000000000000DB0000BE00427900009E00000000000000000000000000000000
+5265E60000000000000000000000003A7D0000DB00218A003A7D0000BE0000000000D200009E0000
+0000000000000000109600000000000000009E0000CA0000AE0000AE0000AA000000000000000000
+00FFFF00FFFF00000000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+00000000000000A600000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000000000000000
+00003A7D0000AE007B6D216B69195A6D104279004A7508000000FFFF00FFFF00FFFF00FFFF00FFFF
+00FFFF00FFFF00FFFF0000000000C60000BE0000B200009E0000B20000B20000CE0000CE0000CE00
+00D2001092006B6910427900298600427900318200318200318200218A00089A00218A00198E0019
+920000A60000A20000A20000000000AA00218E0010960000A20000C6001092000000000000002986
+000896003A8200427D00218A00198E00218E0000B600089600199200109200218A00218A00089A00
+3A7D00199200198E00199200089A00218A00198E0000B20000B20000000000000000000000AE0000
+A60000CE0000000000D20000BE0000DF0000000000BA00009E001096003A7D00298600089A0000A2
+0000AA0000E3001992000896000000000000000000005265E65265E65265E65265E65265E6089600
+089600089600089600089600089600089600089600089600089600089600089600089600D6D2CED6
+D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE
+0896000896000896000896000896000896000896005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E600000000000000000000D20000AA0010960000B20000CE000000
+000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000005265E65265E652
+65E65265E6000000009E0000CA0008960000B20000000000000000000000000000000000000000C2
+0000DF0010920000AA0000BE0000000000A60000A20000C60000B200000000000000000000000000
+5265E65265E65265E65265E65265E65265E600000000AE0000B60000AE0042790031820000000000
+000000DF0000000000000000000000000000000000DF0000000008960000A2004A7508427D0000C6
+00000000089A00009E0000CE0000000000000000A20000CA00089600009E0000CE00298600298600
+00AE0000DB0000000000BE0000000000000000BA00636D10000000FFFF00FFFF00FFFF00FFFF00FF
+FF00FFFF00FFFF00FFFF00000000000000318200000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+0000000000B6000000000000003A7D0000C2007365197B69215275087365195A7110318200000000
+FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000B60000000000AA0000AA0000AA0000AA0000
+9E0000C60000BE00089A0000B200009E007365195A6D10218A00218A004279084279003182003182
+00198E00218A00218A0010920000A60000B20000C60000000000BE0000A20000A60008960000C600
+089600000000000000198E001992002986003182003A7D00198E00109600009E00218A00009E0019
+8E00089A00009E00089600198E00199200198E00198E0019920008960000B60000000000000000B2
+0000CE0000AA0010920000BE0000A600009E0000000000DB0000DF0000000000C200089A00109200
+31820052710831820008960000AE003A7D0029860000000000000000D2000000005265E65265E652
+65E65265E65265E60896000896000896000896000896000896000896000896000896000896000896
+00089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142
+848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6
+D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896005265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000D200009E00009E00
+089A0000B2000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000
+000000005265E65265E65265E65265E60000000000000000000000000000000000005265E6000000
+00000000000000000000C60000BE0000C20000000000000000000000000000000000000000000000
+00000000000000000000000000005265E65265E65265E65265E65265E6000000009E0000CE0000B2
+004A7508427D0000B60000000000E30000DB0000E30000000000BA0000A60000000000000000AA00
+089A0031820042790031820000CA0000000010960000DB0000CA0000000000A60000AE0000B20000
+A200009E00198E00298600218A0000BE0000000000CA0000D700000000009E004279004A75080000
+00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000427900636910000000FFFF00FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF00000000000000FFFF00FFFF000000000000006369106B691973651963
+6D107369195A6D10000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000AA000000000000
+0000000000B20000B20000AE0000D2003A7D00089A0000A600218A003A7D003A7D00218A00298600
+2986003182004A7908318200298600199200218A00109200009E00218A0000A60000A20000000000
+A600089A0010920010960000C20000000000A60000BA00318200198E00318200318200198E001092
+0000BE00109600198E00198E003A7D00198E00218A00218A00218E00109600109600000000000000
+00000000D20000D20000A600089A00218A0000BA0010920000A60000DB0000000000BE0000DF0000
+000000AA0000A6001992002986003A7D005271086369105A71104279080000000000000000000000
+005265E60000000000000000005265E65265E6089600089600089600089600089600089600089600
+089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6
+D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2
+CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600
+000000D70010920000B20000CE0000DF000000005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E60000000000005265E65265E65265E65265E65265E65265E65265E600000019BA4A00
+00005265E65265E65265E65265E60000000000000000000000000000000000000000000000000896
+0000D70000B200000000000000000000009E0000D7000000005265E65265E65265E6000000000000
+00000000D20000D2001992003A7D00089A0000B60000000000DF0000000000000000C20000C20000
+CA000896000000000000004A750800AE00427D004A750800C60000000000C60000B20000B2000000
+0000000000BE0000BE0000B200009E00218A0042790829860010960000B60000000000BE0000D700
+000000000000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000005A6D10636D1000
+0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+00000000736519736519736519736519527108089A00000000000000FFFF00FFFF00000000000000
+3A7D0000A20000C60000000000A60010960010960000A60000D20029860010960000B200009E0021
+8E00298600198E003182003182005A71105A71103182003182004A7508218A00089A00109200089A
+0000A20000A60000000000000000B20008960000A60000A60000A2000000000000000000003A7D00
+4A7508298600089A00198E0000BA00218A00089600218E00198E00089A00218A00298A00198E0000
+9E0000000000AE00089A0000B200009E00218A00218A00218A00089A00109200218A0000AA0000D7
+0000000000E70000E30000000000CE00218A00109600009E00318200218A0010920000A600000000
+0000000000000000000000000000000000003A7D000000000000005265E608960008960008960008
+9600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE8482844241
+42D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF00FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008
+96000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E60000000000000000000000000000000000000000005265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000005265E652
+65E65265E65265E65265E60000000000000000005265E65265E65265E65265E65265E65265E65265
+E65265E60000000000000000005265E65265E65265E65265E60000005265E65265E6000000000000
+00000000000000000000A20000CE0000000000000000000000AA00009E0000E700089A0000000052
+65E65265E600000000000000000000000000000000000000000000000000000000000000E3000000
+0000D200109600198E0000D70000C200000000000000198E003A820000A6003A7D0000BA00000000
+00B600009E00009E0000000000000000CE0000B20000AA00218A00109200198E004A7508198E0000
+000000000000BE0000DB0000B60000BE0000000000B200000000000000FFFF00FFFF000000000000
+004279006369105A6D104A7508000000FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF00000000636D107365197365197365193A7D00427900318200636D1000
+00000000001092003A7D0000000000000000000000000000CE0000AA0000C60000B200009E0000A6
+0000B20000B200009E00198E00218E00218A00199200318200527508427D004A7508298600199200
+198E00298600218A0000B60019920000A20010920000AE0000000000A60000A60000A60000B20000
+9E00089A002986000000000000003A7D00218A00109600109200199200198E00218A00009E001092
+00199200218A0000000000000010960008960000A600109200218A00218E00089A00198E003A7D00
+218A00218E0000CA0000AA0000BE0000000000000000000000D700198E00198E00089A00218A0008
+9A0029860000000000000000000000B2003A7D0000CA0000C2000000000000000000000000005265
+E6089600089600089600089600089600089600089600089600089600089600089600089600089600
+D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF
+FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
+000000000000000000000000000000FFFFFFFFFFFF000000000000000000000000000000FFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2
+CED6D2CE0896000896000896000896000896000896005265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E60000000000000000000000005265E65265E65265E65265E65265E60000000000005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600
+000000000000000000000000000000DB0010920000000000000000000000A600009E0000B20000CA
+0000E30000DF000000005265E65265E600000000000000000000000000C200089A00198E0000A600
+00BA0000000000000000000000CA0000B6005A711000D70000AE0000000000E30000000031820019
+8E00089A00199200000000009E0010960000CE00000000000000009E0000A20000C60000CA0000A6
+00089A00298600218E00000000198E0000000000000000BE0000DB0000000000AA0000CE0000AE00
+0000000000004A79085A7110527108736519636910736519000000FFFF00FFFF00FFFF00FFFF0000
+0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000006B69197365197365193A7D
+00527508636910636D10427908318200000000000000FFFF00FFFF0000000000000000CE00009E00
+08960000B200089A0000A20000C60000B200109200109600109600109600109600198E004A750842
+7900298A002986003182003182004A7508199200218A00089A00009E00089600089A000000001092
+0000B20010960010920000BA00109600427D00218E003182000000003A7D00218A00009E00199200
+218A0000000000000000000000BA00000000089A0010960000BA00089A00089A00218A003A7D0019
+8E00298600298600109600218E00089A0000B60000CA0000AA000000000000000000000000000000
+00000000000000318200089A00198E00000000000000089A00109200427908089600198E00000000
+00D7000000005265E65265E65265E608960008960008960008960008960008960008960008960008
+9600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482
+84424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFF000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF00
+0000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF
+FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CE
+FFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E60000000000005265E65265E65265E65265E652
+65E60000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E600000000000000000000BA00198E00109600218A00298600089A00000000000000
+089A0000A60000BE0000B20000C20000CE000000000000005265E60000000000005265E600000000
+000010920019920000AA0000CE0000000000000000BA0000D70000A2004A750800A60000D70000D2
+00000000000000198E00298600218E00198E0000000000000000BE0000C60000000000000000A200
+089A0000AE0000CE00109600218E003182004A750800000052710829860000000000C20000B60000
+CE00000000089600318200736519527508636D104279004A75085A6D106B69197365197365190000
+00000000FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000
+736519736519736519218A00636D107365193A7D004A7508000000FFFF00FFFF00FFFF00FFFF00FF
+FF00FFFF0000000000C60000BE0000CA0000C60008960010960000A600009E0000A20000B60000B6
+001092004A7908298600199200218A00198E00318200736919427908198E00218A00218A00199200
+109200089A0000000010960000A20000A600009E0000B200198E00427900298600198E0008960000
+0000000000000000000000000000298600198E0010960000000000000000AE0000BE001092001092
+00198E00198E00298600298600198E00198E003A7D00218A0000C60008960000BE0000000000E700
+000000000000009E00298600298600089A000000000000000000001096006B6919198E003A7D0042
+7908089A0000BE000000000000000000005265E65265E65265E60896000896000896000896000896
+00089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFF
+D6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+FF00FFFF00FFFF00FFFF00FFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+00FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFF
+FFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896
+000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000000000
+000000005265E65265E65265E60000005265E65265E65265E65265E65265E65265E65265E6000000
+5265E65265E65265E65265E6000000000000000000000000000000000000109200089A00198E0021
+8A00109600000000109200218A00009E0000BA0000C60000D20000D2000000000000005265E60000
+0000AA000000005265E6000000009E00089A0008960000000000E70000000000B60000AE00427900
+4A750810960000B20000D20000DB000000000000003A7D00218A0000000000000010960000C60000
+000000BE0000AA0000000010920008960000B20000A60000BA00427D00318200000000218A003A7D
+0010960000000000CE0000BE0000D700000000009E004279007B65195A6D105A6D10636D105A6D10
+6B69197B69197B6D216369106B6919000000000000636910000000FFFF00FFFF00FFFF00FFFF00FF
+FF00FFFF000000007365196B69107365195A71100896005275085A6D10427900427900000000FFFF
+00FFFF00FFFF00FFFF00FFFF00FFFF0000000000B20000BE0000AE00089A0000C20000A600109200
+00BA0000B20000AE0010920000B600218A00198E00198E001096003A7D003182004A75083A7D0029
+8600109600198E0010920000AE00218A0000000000AA0000A60000A200009E00109200218E004279
+08318200109600318200218E000000001992000000003A7D00218A00109200089600218A00000000
+00C200198E00089A00218A00089A003A7D00318200298600218A003A7D00218E0010920000D20000
+BA0000000000000000DF0000000000D2000000003A7D004A7508427900298A001992004279003A7D
+00218A00218A000000000000000000000000000000000000000000005265E65265E65265E6089600
+089600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE84
+8284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF00FFFF00FFFF00FFFF
+00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600
+0896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E60000005265E65265E65265E65265E652
+65E65265E65265E60000000000005265E65265E6000000000000009E0000DB0000000000DB0000DB
+00000000000000198E00218A00109200000000009E0000BE0000C20000AA00089A0000DB0000CA00
+0000000000005265E600000000AA000000005265E600000000CA0000D70000000000000000000000
+000000D20000C2004A75084A750810960000B20000AE0000DF0000000000000000000000000000B2
+0000B20010920000C60000A60000000000A200000000089A0000B20000A60000BA0000BE003A7D00
+4A750800000019920031820000000000BA0000DB0000A200009E0000A200000000198E0010920031
+82004279005271085A6D106B69196B69197365196B69197B71217365196B69106B6910000000FFFF
+00FFFF00FFFF00FFFF00FFFF00FFFF000000005A6D107365197365195A7110218A006369105A6D10
+636D10000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000BE00009E0000
+AE0000A60000A600089A0010920000B60000AE0010920000BA00198E00109200109600089A003182
+005A6D10427908298600298600198E00109600089A00089A00009E0000000000B20000A20000B600
+109200109600109200318200427900199200298600198E00218E00000000000000318200198E0010
+9600298600198E0000000000B200198E00218A00218A00198E00218A00318200298600218A00218A
+0010920000A20000D70000000000E70000E70000000000D700089A000000003A7D004A7508527110
+5A6D1042790800A60000000000000000000000000000000000000000000000000000000000000052
+65E65265E65265E60896000896000896000896000896000896000896000896000896000896000896
+00089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284
+424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF00
+0000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFF
+FFFFD6D2CED6D2CE0896000896000896000896000896000896005265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000C60000AE00
+218A00000000000000009E0000CE0000000019920019920000BA0000000000A600009E0000A60000
+D70000D70000B20000AE000000000000005265E600000000000000BA000000000000000000000000
+0000AA00009E0000CA0000E30000BE00009E0000AA003A7D00527508218A0010920000B60000D200
+00000000DB0000D70000000000000000000000A20000000000A60010960000CA0000000000AA0010
+920000A200198E0000A200218A00000000318200089600000000089A0000C20010960000BA00089A
+0000BE000000002986005A71105271103A7D005275087365197365195A6D106B69197369196B6919
+636D10089A00109600000000000000FFFF00FFFF000000000000005271085A6D1063691073651973
+6519009E00636D10527508527108000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+0000000000A60000A60010960000A600009E00199200009E0010960000AE0010920000BA00089A00
+089A00198E002986003A7D00636D105275083182003182003A7D00218A00109200089A0010960000
+A60000A60000B200089600109600218E00218A004A75083182003A7D003A7D000896001096000000
+00089600000000000000000000089A003A7D0000000000A600218E00089A00198E00218A00318200
+298600318200218A00198E00198E0000C60000CA0000000000E30000E30000000008960000B20000
+000000B6004A75084279004A7508218A00000000000000000000000000089A0029860000D70000A6
+003A7D00009E000000005265E65265E6000000089600089600089600089600089600089600089600
+089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6
+D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFF848284FFFFFF848284FFFFFF848284FFFFFF848284FF
+FFFF848284FFFFFF000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+00FFFF00FFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF
+FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFF
+FFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E60000005265E65265E65265E65265E600000000000000000000
+000000AA0000D200089A00218A0000A20000000000A60000BA0000000010920000B60008960000BA
+0000000000DF0000B20000AE0000AE0000B20000C2000000000000005265E600000000000000BA00
+00DF0000000000C20008960000C60000DB0000AE0000AE0000B60000D70000AA00218A003A7D003A
+820000CE0000AA00089A0000000000E70000AA0000B600009E0000AE0000000000B20000A20000C6
+0000CE0000D20000000000BA0000A200089A00089A00000000318200427900427900000000109600
+00A600009E00109600009E0008960000000000000000000000A200198E00298600636D10636D1063
+6D107B65197B7121736519527108009E000000007365190000000000000000005275082986005271
+085A71107365197B6519736519109200527108636D107365195A7110000000FFFF00FFFF00FFFF00
+FFFF0000000000000000000000A60000A60000A20000AA0000AA0000AE0010920000BE0000BE0000
+BA0000BA00009E0000B600198E001096003182003A7D007365195A6D10427900318200198E00198E
+0000BE00009E0000A60000A600089A00109200089A00218E00109200218E00198E00298600198E00
+427D00109200000000218A00218A00218A00009E00198E00000000089A00000000109200218A0010
+96003A7D00218A00089600318200218A00109600298600009E0000A20000BA0000000000DF000000
+0000C600089A00218A0000AA00000000009E000896000000000000005A71105A7110636D10427908
+298600427900218A0000AE000000000000000000005265E600000000000008960008960008960008
+9600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2
+CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000
+FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008
+96000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E60000005265E65265E60000000000
+0000000000000010920000A200218A00218A0000AA00199200109600000000198E00198E00000000
+10920000A60000A60000AA0000000000C20000A60000D20000AA0000C60000D70000000000000052
+65E600000000C20000E70000CE0000000000DF0000AE0000D70000CA0000DF00089A0000AE0000C2
+0000DB001096002986003A7D00218E0000AA0000AA0000000000B60000E70000DB0008960000C600
+08960000B200000000000000000000000000000000009E00109200089A00009E0000000010960042
+79084A7908318200000000089A00009E0000B20000000000CE00198E003A7D003182000000001092
+003A7D00198E003182005271087365196B69197365190000000000007365197365190000004A7908
+636D103182005A71105271087B65196B69107365196B6919089A00427900527508527108636D1000
+0000FFFF00FFFF00000000000000FFFF00FFFF00000000000000109200089A00009E0000A60000A6
+0000B600109200109200009E0010960010920000BA00198E003A7D004279004A75084A7508318200
+298600218A00089A00218A0000BE00009E00109200009E00089600198E00298600198E00198E0019
+9200298600198E00198E00298600109600000000000000089600198E00109600109200089A000000
+0000C200109200089A003A7D00218A00218A00298A00298600298600218A00089A0000C600089600
+00000000E30000000000000000C200298600218A00089A000000000000000000003A7D0042790873
+651910960000B20000A20000B60000AA0000A6000000000000000000000000005265E60000000000
+00089600089600089600089600089600089600089600089600089600089600089600089600D6D2CE
+D6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF00FF
+FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF
+FF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2
+CE0896000896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000005265E65265E6
+5265E600000000000000000000000000000000CA0000B20000C6003A7D0019920029860000A20000
+AA0000000000000000CE0000C60000DF0000C60000000000000000C60000B20000A20000A20000BA
+00089A000000000000005265E600000000000000000000000000000000000000BE0000DB00089600
+00C20000CA0000AE0000AE0000C60000A2003A7D00198E0000AE0000B60000A20000000000AA0000
+C60000BE0000CE0000A600000000000000FFFF00FFFF0000000000000000000000000000BA001096
+00109600218E0000000031820042790800000000000000AA00198E00109200089A0000000000C600
+19920031820031820000000000A2005271106B69105A71107365197365190000004A75086B691963
+6D105A6D100000003A7D005A6D105A6D105271085A71107365197365196369105A6D102986005271
+084A7508527108636D10427900000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000
+00AE00089600009E00109600009E00199200198E00109200089A00009E00198E0019920029860052
+7508736919427908218A00318200218A00218A0010960000B600009E0010920000BE00198E00198E
+00109200089A00218E002986004279001992003A7D00000000000000FFFF00FFFF00000000000000
+218A00218A00218E00000000000000218E00089A00199200298600298600298600218A00198E0019
+8E00009E0000D70000000000DF0000000000000000D2000000004A75084A790800A2000000003182
+002986004A79083A7D00527108318200218A0000A600089A0000BE0000000000D20000C600000000
+00000000000000000000000008960008960008960008960008960008960008960008960008960008
+9600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241
+42848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFF
+FFFFFFFFFFFFFFFF000000000000000000000000000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000000000000000
+000000FFFFFFFFFFFFFFFFFF000000000000000000000000000000FFFFFFFFFFFFFFFFFF000000FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFF
+D6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896005265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E60000005265E65265E65265E600000000000000E700089A0000AE0010960000D200089A000896
+00218E00318200198E0000BA0000000000000000000000DB0000C20000000000B20000C60000D700
+00CA0000C60000C60000B60000AA0000BA0000000000000000000000C20000CA0000DF0000D70000
+000000BA0000AE00009E00089A0000D20000AA0000BE0000B60000A60000BE0000A60000A200089A
+0000C60000000000CE0000C60008960000AE00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+000000FFFF00000000199200109200089A00000000000000000000298600218A00218A00009E0000
+9E00218E00198E00000000198E00218A00318200427900000000009E004A75086369100000000000
+00527108636D10736519636D10000000318200427D007B69195A6D105275085271105A6D10736519
+6369105A6D104279085271084279005271104A75084279083A7D00000000FFFF00FFFF00FFFF00FF
+FF00FFFF00FFFF0000000000BE0010920000BA0000BA0000BE0000BE00089A00009E00198E00218E
+00089A002986003182003A7D006369103A7D003A7D00218A003A7D0029860010920000B200218A00
+218E00089600218E00109200009E0000BA00198E00298600427900089A00000000FFFF00FFFF00FF
+FF00FFFF00FFFF00FFFF00000000089A00000000000000089600000000000000218A003A7D00218A
+003A7D00218A00109600198E00089A0000000000E30000000000C20000BE0000AE00000000527110
+4A75083A7D00000000736519218E00199200009E00298600198E0042790042790000A60000B20000
+000000A20000BE0000A20000000000000000BE000000000000000896000896000896000896000896
+00089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CE
+D6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84
+8284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF00FFFF00FFFF00FFFF00FFFF00FF
+FF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6
+D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E600000000000000000000CE0000B20000C20000A600
+00D70000BA00109200089A00198E00298600009E0010960000A600000000000000009E0000B60000
+000000B60000C20000D70000CA0000D70000B60000C60000AA00009E0000000000000000000000CE
+0000D70000BE00009E0000000000DF0000AE00089A0000B60000C60000DF0000DB0000C20000A200
+00CA0010960000A60000AA0000AA0000000000B20000A60000AA0000A600000000FFFF00FFFF00FF
+FF00FFFF00FFFF00FFFF00000000FFFF00000000009E00109200218A00000000000000298600218A
+00298600198E0000BA00109600198E00198E00000000198E00198E00218A00318200427900000000
+218A000000005A6D105271105A6D105271087365190000000000004A790800BA005A6D107365195A
+71107365195A6D10736519636D10218A004A75084A75084279005271085A6D103A7D00000000FFFF
+00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000218A00109200089A00109200089A00
+089600109600198E00089A00218A002986002986004279002986003182002986002986007369197B
+7921198E00089A000896001992001992003A7D00109200199200198E00089A00198E00218E00198E
+00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000000000198E00000000218A003A7D00
+298600000000298600318200298600318200218A0000AA0000C60000000000DF0000000000B60000
+A600000000109600427900736519318200000000527508218A0031820000C20000D20000CA000000
+0000000031820000000000000000D20000A20000A60000000008960000B6003A7D00000000089600
+089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE84828442
+4142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000
+00000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600
+0896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000B20021
+8A00089A00198E00198E00109600198E003A7D002986001096003A7D0000A200089A0000D2000000
+0000D20000E70000C20000000000CE0000CE0000B20000D70000BA0000D70000B600000000000000
+00000000000000000010920000D70000D70000DB0000C200000000089A00009E0000B60000B20000
+AA0000AA0000B20000CE0000AE0000B20000A600009E0000B200000000109600198E001096000000
+00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00000000199200089A00
+000000089A002986003182003A7D0029860019920019920010920042790000000000000029860019
+92003182002986004279080000000000002986005271085271085275085275080000005271085A6D
+10218A005275087B65197365195A6D105A7110636910636D103A7D006369105A7110527108636D10
+4A7508298600000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000198E0008
+9600199200109200218A00089A00218A00298600198E003182003182002986003A7D003182003A7D
+00298600198E00318200199200089600089A00009E00109200089A00089A00218A00298600198E00
+298600218A00218A00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000019
+8E00000000218E00198E00198E00298600000000218A00298600109200218A0000B20000000000DF
+0000000000BE00009E001096000000005271082986005271084A79080000004A7508298A005A6D10
+527508427D00089A00000000000000000000000000198E00218A0019920000CA000000003A7D0000
+9E000000005265E60896000896000896000896000896000896000896000896000896000896000896
+00D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6
+D2CED6D2CE0896000896000896000896000896000896005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000
+0000000000C600009E00198E0000BE0000B600218A0000AA00198E00009E0000B20000BA00109200
+089A00009E0000000000000000000000000000000000000000C20000C20000CA00009E0000000000
+000000000000000000BA0000D20000000000000000000000DB0000BE0000BA0000C2000000001096
+0000DB0000AA0000AA0000DB0000AA0000DF0000B20000BE0000A200218A00198E0000A600000000
+00A20000AA0000B200000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FF
+FF0000000000BE00089A00000000109600218A00318200318200198E00318200298A00089A00198E
+00089A0000A2000000002986003A7D003A7D003A7D00298600218A00109600218E004279004A7908
+6369100000005271085271103182005A6D105A6D107365195A6D105A6D10527508736519427D005A
+71107365195A6D104279004A75084A7508427900000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+00000000198E00089A00089A00109600218A00298600198E002986002986003A7D003A8200298600
+3182003182004A7508298600298600198E00089A00318200109600109200009E00109600218A0008
+9A0010960000BA001992003A7D00109200089A00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+00FFFF00FFFF00000000218A00000000089600198E000000000000000000003A8200298600199200
+00AA0000000000DF00000000109200198E0000D70000AA000000007B6519009E0052750829860000
+00002986004A7508089A00089A00009E0000000000000000000000000000000000000000A200009E
+000000000000000000000000005265E65265E6089600089600089600089600089600089600089600
+089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84
+8284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2
+CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+00000000000000000000000000000000000000000000CE0000C20000DF0000DB00218E00089A0000
+A60000D20000BE0000AE00089A000000000000005265E600000000000000E700009E0000C20000CA
+0000E30000000000BE0000C60000AE00089A0000D70000BA0000000000000000000000A20000BE00
+00D70000CA00009E0000000000B60000A200009E0000D700009E0000A60000A20000C60000A60019
+8E0000AE0000BE0000000019920000A20000B200089A00000000FFFF00FFFF00FFFF00FFFF00FFFF
+00FFFF00000000FFFF00000000089A00109200000000218A003A7D00298600318200318200218A00
+3A7D00298600089600218A00109200218A00198E000000000000000000000000002986003A7D0029
+8600089A003A7D004279084279080000004A79084A75085A71105A6D10527108636D105271085275
+085271087365194279004279004A75084A75083182002986004A7908318200000000FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF00000000198E003A7D00089A00089A003A7D002986002986003A7D0042
+79004A75085275083182003A7D00318200318200298600298600298600109600527108089A00218A
+00089A0000BA00198E00109200198E001092000896002986003A7D001092004A7508000000FFFF00
+FFFF00FFFF00FFFF00FFFF00FFFF00000000199200199200000000000000000000298600218A0000
+0000000000218A0000A20000DF0000000000000000A600198E0010920000D70000BE000000002986
+005A711042790000AA000000001092000000000000000000000000000000000000000000005265E6
+5265E600000000000000000000BE0000AA0000AA000000005265E65265E608960008960008960008
+9600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFF
+FFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008
+96000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E600000000000000000000000000000000E3000000000000000000001092
+00089A0008960000CE0000D20000A20008960000AE0000DB000000000000005265E6000000000000
+00BE00009E0000C20000000000000000A20000BE0000A20000DB0000AE0000C60000CA0000000000
+000000000000C60000C20000C20000CA0000C60000000000DB00009E0000DB0000A60000DB00089A
+0000B20000B20010920010920000BA00298600000000109200089A0000BE00089A00000000FFFF00
+FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00000000009E00000000000000089A0019920019
+8E002986003A7D00298600298A003182003A7D003A7D00298600298600318200199200298A00218A
+000000003A7D00218A003A7D00218A003182004279000000004279005A71105271085A6D10636D10
+5A6D10636D10636D107365196369104279003182004A75085A71104279004279083182004A790800
+0000000000000000000000FFFF00FFFF00000000000000298600109600218A00198E001992003182
+003182003A7D003A7D006B69107365196369107B6D215271084A7508298600218A00318200218A00
+3182004A7508109200198E00109200218A00089A00218A00199200218A00218A00218E00427D0029
+8A00318200000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000218A00298600218E001096
+00198E00298600198E00199200000000000000000000000000000000009E000896003A7D00089A00
+00DB0000DF00000000198E00109600427D0008960000DF0000000000000000000000000000000000
+00000000000000000000000000005265E60000000000000000000000000000000000005265E60000
+00089600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE
+848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896
+000896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E60000000000005265E6000000000000000000000000
+00000000000000000000000000000000000000CA0000BE0010920000CA0000CA0000000000000052
+65E65265E600000000000000CE0000D70000000000000000CE0000A20000A60000AA0000BE00089A
+0000AA0000CE0000C60000000000000000DB0000D70008960000D70000B20000000000CE0000C200
+009E0000AE0000DB0000CA00009E0000AE0000A60000A600199200000000109200218A00218A0010
+9600109600198E00000000000000FFFF00FFFF000000000000000000000000000000000000000000
+00000000198E00199200089A003A7D00318200218A002986003A7D00298600298600298600318200
+427908318200318200218A002986000000000000003182003A7D003A7D003A7D0000000042790031
+82006369105A71104A7508527508527108636D105271085A6D10527108318200636D105275084A75
+084A7508318200298600000000109200218A00199200000000000000298600298600298600218A00
+3A7D003A7D003182004A75083A7D003182007365197365197B6921736519636910527108636D103A
+7D00298600298600089600427900427900218A00218A001096001992002986002986004279003182
+003A7D00218A00218A003182004A7508198E00000000000000FFFF00FFFF00000000000000198E00
+318200089600218A00198E00198E00199200198E00198E00198E0000000000E30000000000000008
+96003A7D0042790000CE0000CE0000AE0000000000A2004A750800A600089A0000B200000000009E
+000000000000000000000000000000000000000000000000000000005265E6000000000000000000
+5265E65265E65265E600000008960008960008960008960008960008960008960008960008960008
+9600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241428482
+84424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CE
+FFFFFFD6D2CED6D2CE0896000896000896000896000896005265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000005265E600000000
+00000000005265E65265E65265E65265E6000000000000000000000000089A000000000000000000
+000000000000005265E65265E65265E600000000CE0000DB0000000000DB0000C60000AE0000AE00
+00CE00009E0000AA00009E0000DF0000B60000C60000000008960000D70000C60000D70010920000
+CE0000000000000000B60000B20000A20000C60010960000C200089600009E00198E00009E000000
+00218A00218A00109600199200218A00218A00089600218E00000000000000000000000000000000
+000000089A00218A00000000109600009E00318200199200218A002986002986002986002986003A
+7D003A7D004A75082986003A7D004279003A7D00218A002986003A7D002986000000002986003182
+003182000000003182003A7D004A75085271084A75085271085A6D104A75085A6D105A6D104A7508
+5271086B69194A79084A7508427900427900000000089A00218A002986003182003A7D0029860031
+82003A7D002986003A7D003182002986004279002986004279002986007B69217B71217365197365
+19636D10736519427D004279003A7D00298600218A00427908109600089A00198E00198E00218A00
+4A79083182003182003182003182003A7D003A7D003A7D004A7508198E00218E00218A0000000000
+0000318200198E00198E003A7D00218A00218A00318200298600298600199200198E00218A000000
+00000000009E00089A002986004A75084A750800D200089A0000CA00000000000000109200527508
+218A00198E000000003A7D005A6D10427908318200636D104A75083A7D0000B20000BA0000000000
+00005265E65265E60000005265E65265E65265E65265E60896000896000896000896000896000896
+00089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE
+D6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFF
+FFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E60000005265E60000000000005265E65265E65265E65265E65265E65265E6000000000000000000
+00000000E30000CA000000005265E65265E65265E65265E600000000000000CA0000000000C60000
+BA00009E0000CE00009E00089A00198E0000A60000B60000DB00089A0000000000000000A60000C6
+0000D20000B20000DF0000AE0000B20000D20000DB0000D20000A20000CE0000AE0000A60000A600
+00A600109200109600000000089A00198E00198E00298600218A00198E00199200218E00089A0010
+9600000000000000218A00089A0000BA0000B600000000089A00109600218E003A7D001992002986
+00298600298600218A002986003A7D003182004A75083182003A7D003182003182002986003A7D00
+318200000000427D003A7D000000000000004279003A7D005275085A711052710852710852710852
+71085271105A71103182004A79084A75085271083A7D003A7D00000000089A00298600218A00089A
+00218A00427D002986003A7D003182003A7D003182003182003A82004279004A75083A7D005A7110
+7B6D217B65197B69196B69107B71217365194279003A7D00318200298600218A00198E00198E0010
+9600198E003A7D00089A000896003A7D003A7D003182003A7D004279003182004A7508198E003A7D
+00089A00009E002986000000000000000000004A75082986001992003A7D00218A00298600298600
+199200198E0000000000000000000029860000A20052750852711029860000BA00198E0000000010
+92003A7D000000004A750829860042790042790000000000000000000000000000D20000C200089A
+0029860000A6001092000000000000000000000000000000005265E65265E65265E6089600089600
+089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6
+D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF
+FF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600
+0896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E60000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E60000005265E65265E65265E65265E60000000000000000005265E65265E652
+65E60000005265E65265E60000000000000000000000005265E65265E65265E65265E60000000000
+0000000000DB0000C60000B60000CE0000C60000C60000C6001992003A7D0008960000DB00000000
+00000000DF0000AA0000CA0000D20000AA0000DF0000A20000DB0000C60000B20000CA0000AA0000
+D20000A200109600089A0000A600109200198E00000000199200298600298600318200298A00298A
+00298600298600199200000000089A00218E00218E00198E00218E00198E00000000109600109600
+198E003A7D00198E002986003182004279002986003182003A7D004279003182003A7D004279003A
+7D003A7D003182003182004279004A79082986000000000000000000004A79084A75085A6D104A75
+084A7508527108636910636D107B65194279004279084A79085A7110318200000000000000089A00
+1092001096003A7D002986002986004A75083A7D003A7D004279004279084279084A790842790052
+71084279004A75085A71107B75217369196B69107365197B71217B71217365194279003A7D002986
+003A7D00218A00199200089A003A7D00198E00218A00218E00427D004279003182003A7D004A7508
+318200218A00298600198E00218A00089A0029860000C200198E00109600000000199200198E0010
+9600218A00218A003A7D0008960000000000D20000B600000000109200198E005271083182001096
+0000C20000AE000000004A75083A7D004A75080000003182005A6D105A6D1010920000D200089A00
+00D7000000000000000000000000000000000000000000000000000000000000000000005265E652
+65E65265E65265E6089600089600089600089600089600089600089600089600089600089600D6D2
+CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFF
+FFFFFFFFFFFFFFFFFF848284848284848284848284848284848284848284FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000
+00000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6
+D2CE0896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E60000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E60000000000000000000000005265E65265E65265E65265E60000
+000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E600000000000000000000AE0000B60000DB0000BE00218E0000BE0008960000AA00089A0010
+920029860000A60000000000CE0000000000DB0000DB0000C60000D70000B20000AA0000A20000DB
+0000B20000BE0000BA0000A20000A600109200009E00109200109200000000218A00218A003A8200
+2986004A7908298600318200298600000000000000199200199200198E00198E00218A00198E0021
+8A00000000089A00198E00198E00198E00198E00298600298600318200218A003A7D003182002986
+003182003182003182004A79083182002986004A75080000000000000000002986003182003A7D00
+0000002986004A75085275084A7508636D107B65195275084A75084279005271085275083A7D0000
+00004A7508298600109600109200298600218A002986003182003182003182004279004A75083182
+003182003A7D003182007365194A75084279007365197B75217B71217B71217365196B69197B7921
+7B69193182002986003A7D00298600298600199200198E00089A00199200198E00199200218A0031
+82003A7D003A7D003182003A7D00198E00218A002986001992003A7D003A8200198E00218A003182
+00000000000000000000000000218A00198E00089600000000218A0019920000BE00000000109200
+427900527108218A00198E0000BA00089A00000000199200318200199200000000199200636D1008
+9A007365194A790800A20010920000C2000000000000000000000000000000000000000000000000
+000000000000005265E65265E65265E65265E6089600089600089600089600089600089600089600
+089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442
+4142848284424142FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8482
+84FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF0000000000
+00000000FFFFFFFFFFFFFFFFFF000000000000000000FFFFFFFFFFFFFFFFFF000000000000000000
+000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFF
+FFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896005265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E60000000000000000000000005265E6
+5265E65265E60000000000000000000000000000000000005265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E600000000000000000000AA0000C20000D70000CA0000D70000BE
+0000000000000000000000AE0000000000000000A60000000000CA0000B60000C60000B60000B200
+00C60000CE0000A200009E0000AE0000CE0000C60000A20000AE0000B200009E00089A00089A0000
+0000218A00218A002986003182004A79083A7D004279000000000000002986002986002986001992
+00198E00218A00198E00218A0000000000BA00298600198E00218E00198E00318200218A003A7D00
+3A7D004279083182004A75083182004279080000000000000000000000000000004279084A750831
+8200318200218A004279000000003182003A7D004A75084A75085271087365194279005271084279
+003A7D003A7D003A7D00000000318200089600109600218E002986002986002986003A7D00318200
+4279004A75083182003A7D003182004279003182004279004A7508527508636D107365197B71217B
+69217B69217B6D21736919427900218A003182004A75082986003A7D00198E00298600198E002986
+00199200298600218A00298600198E00318200218A003A7D0010960029860000BE00218A004A7908
+3A7D00218A00298600298600298600218A0010960029860000000000000000000010960008960008
+9A00000000218E003182005A7110527508218A0000B60010920000DB000000004279005271087365
+190896000000000000000000003A7D00427908298600527508218A0000BA0000DB00000000000000
+0000000000000000005265E65265E60000005265E65265E65265E65265E608960008960008960008
+9600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2
+CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000FFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF00
+0000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+D6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960052
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000
+00000000000000005265E600000000000000000000000000000000000000DF000000000000000000
+005265E60000000000005265E65265E65265E65265E65265E65265E600000000DF00000000000000
+00000000000000000000000010920000000000A60000000000A60000B20000A20000CA0000000008
+960000D70000DB0000D70000DB0000AA0000BA0000A200089A0000C60000B200218A0000C60000A6
+00089A00089A00218A000000002986002986002986003A82003182003182000000004279084A7508
+318200218A00089600218A00198E00109600009E0019920000000000B600218A00218E00198E0008
+9600218A003A7D002986003A7D003A7D003A7D004279080000000000003A7D003182004279083A7D
+003182004279083A7D003A7D00427D003A7D003A82000000004A75083182003182005A71104A7908
+5A6D104A75084A75084279083A7D003182000000003A7D00218A004A7508198E00198E0031820029
+86002986004279084A75083A7D004A75085271085275083A7D002986004279003182005275084A75
+085271087365197365197B69217365196B6919218A00218A002986004A75085271084A7508298600
+298600298600109200298600089A003A8200198E000896002986002986003A7D003A7D0008960029
+8600218A00198E003A7D00009E00427900218A002986004279003A8200318200218A00198E00009E
+0000A200198E00298600009E0000BA000896002986004A75085A6D10298600089A00089A0000CE00
+0000000000000000000000003A7D0052710800DF000000000000006369103A7D0063691000A60029
+8A003A7D0029860000DF0000CA001092000000000000000000005265E65265E65265E65265E65265
+E6089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284
+424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFF
+FFFF848284000000000000000000000000000000848284FFFFFF848284FFFFFF848284FFFFFF8482
+84FFFFFF848284FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF0000000000
+00000000000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896
+000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E60000000000000000005265E60000000000000000
+005265E65265E60000000000000000000000005265E600000000000000000000000000D200000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000008960000DB00109600089A00218A0019920000A20000B200109200089A
+00009E0000A20000000000D70000D70000AE0000DF0000A60000AA0000A20000CE0000A20000AE00
+00AA00009E0000A20000AA00109200109200298A00218E000000002986002986002986004A790800
+0000000000318200427D004A7508298600298600298600199200198E003A7D00109200000000218A
+00109600009E00089A001992003A7D00218A00298600318200318200318200000000427900427900
+4279004279083A7D004A75084279084A7508318200298600318200427D00218A0000000000000031
+8200427900427D004A75084279085A6D104279084A75085275083182000000003182002986002986
+00109600298600218A003A82003182003182003182003182004A75084A75084279004A75083A7D00
+318200427900427D004279004279087365195A6D10527110636D103182003A7D0029860029860031
+82003A7D00318200218A00298600218A00218A004279004A7508427900318200198E003A8200427D
+003A7D003A7D00198E00198E00089600298600218A003A7D003A7D00318200318200318200298600
+3A7D00218A00198E0000C600089A0029860000A20000A600089A00218A002986003A7D0031820019
+8E0000BA00198E0000A60000000010960000D70000BA0000000000B200218A0000DB0000C6000000
+00218A0029860031820000B20000C20000C600318200089A000000000000000000005265E65265E6
+5265E65265E65265E65265E608960008960008960008960008960008960008960008960008960008
+9600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241428482844241
+42FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000
+FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFF
+D6D2CED6D2CE0896000896000896000896000896005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000000000
+00000000000000000000000000000000000000000000000000DF0000000000000000000000DB0000
+E700089A0000000000AA0000CA0000C60000C20000BA0000CA00009E0000000008960000B6000000
+0000000000000000000000000000000000AE0000000000D70000AA0000C60000CE003182004A7508
+109200089A00218A003A7D00218A0000000000000000CE0000D70000C20000AA00089A0000CE0000
+CE00009E00009E0000A20000B20000A200009E0008960010920000BE00089600089A00000000218A
+002986002986000000000000004A75084279003A7D003A7D004A7508298600318200218A003A7D00
+198E00109200000000199200198E00009E00089A001096003A7D00218A003182004A750800000000
+00003182004279004A75084A75084A75085271084A75084279004279003182003A7D004A75084279
+003182002986003182000000003A7D004A7908427D004279004279004279083A7D00427900318200
+0000002986002986003A7D003A7D00298600427D004279004A79083182003A7D0031820052710852
+71084A75084A79084279004279003A7D003182003A7D005275084A75084279004A75083182002986
+00298600218A002986003A7D00218A00218A00218A002986003A7D00218A00198E00427900427900
+318200298600298600298600218A003A7D00218A00198E00198E00318200198E003A7D003A820031
+82003A7D003A7D00218A00298600198E0000A200198E00198E001092001092001992003A7D003A7D
+004A7908427D0010960000B600089600298600109200000000427900089600009E0000DB00000000
+00000000DF0000C60000DF0000000000000000B20029860000CE0000E30000000000000000000000
+00000000005265E65265E65265E65265E65265E65265E60896000896000896000896000896000896
+00089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE
+848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000
+00000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FF
+FFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFF
+FFFFFFFF000000FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6
+D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896005265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000005265E652
+65E60000000000000000005265E600000000000000000000000000CA0000000000000000CA000000
+0000000000000000000000E30000AE0000000000B20000D20000C20000A60000CA0000D700000000
+009E0000B600089A0000A60000DB0000CA0000000000000000BE0000D20000000000000000AA0021
+8A00218A003182004A7508009E0010960010920031820031820029860000000000000000D70000A2
+0000B200089A0000A20000C60000CA0000C200089A0000B20000A200089600109200109200199200
+109600089A000000003A7D003182000000000000004A75083182003A7D004279005271083182003A
+7D003A7D00199200427900089A00109200000000198E00199200109600089A00198E002986002986
+003A7D004279000000003182004279005275085275087365195A6D10636D105A6D105A71105A6D10
+4279003182003182004279003A7D003A7D004279000000004A79083A7D004A75084279084279003A
+7D004279084279000000003A7D00218A00298A003182003A7D003A7D003182003182003182004279
+00427900527108427D005275085A6D105271105A71105275084279083182003A7D004A75084A7908
+4A7508318200318200318200218A003182002986002986002986003182002986002986003A7D003A
+7D00198E00427908427900318200218A004A7908298600298600199200009E00218E00298600198E
+00218A002986003182003182004279083A7D00298600218A0000B600109200089A00199200109200
+427900109600218A003A7D00527508298600218A00218A00198E0029860000B2000000005A71107B
+6921218A0000AE0000AA0000000000000000000000000000000000000000C200089A003A7D00218A
+000000000000000000000000005265E65265E65265E65265E65265E65265E65265E6089600089600
+089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFF
+FFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF8482848482
+84848284848284848284848284848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF0000
+00FFFFFFFFFFFFFFFFFF000000000000000000FFFFFFFFFFFFFFFFFF000000000000000000000000
+FFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600
+0896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000
+000000000000000000005265E6000000000000000000000000000000000000000000000000000000
+00D20000CE0010920000B60000AA0000000000000000DB00009E0000000000A60000D70000C20000
+BE00089A00000000009E0000DB0000BE0000DB0000B20000C60000AE0000000000D20000DF0000C2
+0000DB0000D200000000089A00109200198E00298600218A00009E00198E00089600298600218A00
+00000000A20000AE00009E0000CA0008960000AA0000B200089A0000AE0000A20000B20000AA0010
+9200009E0010920000BA00198E00109600000000000000000000199200318200427D004A75084A75
+084279085271085275083A7D00318200198E00198E00199200089A00000000199200218A00089A00
+089A00109200109600218A003182000000003A7D003A7D005A6D106369107365197B71217365197B
+69217365197B65197365195A71104279003A7D002986004279003182004279000000003A7D004279
+083A7D003A7D004279005275080000000000000000003A7D003182002986003A7D00427900318200
+4A75084A79084279084279004A75085A71105271105A6D106369107365195A71105A71105A6D104A
+75084A75083182004A79084A75083A7D00298600318200218A002986003A7D00318200218A00218A
+00318200298600218A00298600199200427900298600218A003A7D00298600218A002986003A7D00
+089A00198E002986003182003182004279083A7D003182003A7D00318200318200198E0010960019
+8E00298600089A00198E002986000896002986003A7D00427900298600218A00218A00198E003A7D
+00218A000000004279003A7D003A7D003A7D00109600009E0000E30000CE0000E30000E300000000
+0000000000000000000000000000000000000000000000005265E65265E65265E65265E65265E652
+65E65265E6089600089600089600089600089600089600089600089600089600089600D6D2CED6D2
+CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08
+96000896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E60000000000005265E65265E65265E65265E65265E6
+5265E60000000000000000000000000000000000005265E600000000000000000000000000000000
+000000000000BE0000000000A20010920000A20000A60000A20000A60000CE0000DB0000DB000000
+0000A20000D20000CE0000B20000000000000000CE0000A20000AA0000BA00009E0000CE00109200
+00000010960000C20000C60000D200009E0000000000AE0000A20000B60000A60000BE0000AA0019
+8E0000CA0008960000AE00000000009E0000BA0000CE0000BE0000BE0000BE00089A0000BE001096
+0010920000A600009E0000B20010920000C200298600218A00000000000000198E00427900218A00
+089A002986003A7D003A7D003A7D004279003182003A7D00427900218A00198E00199200198E0000
+0000198E00089600089A00427900198E002986003A7D003A7D000000004279004A75086B69196B69
+19636D107365197369197B69217B6D217B71216B69107365197365194279084279083A7D00298600
+3182000000003A7D003A7D003182003182003182004279000000004A79083A7D003182003A7D0029
+86003182003182003A7D003182004A75084279003A7D00427900636910636D107B69197B75217B6D
+215A6D105A6D105A6D104279004279084279004A75083182003A82002986003A7D00298600298600
+218A00218A003A7D002986004A7508318200218A00218A00218A004A75082986003182003182004A
+79082986002986002986002986002986002986002986002986005275084A75080000000000004A75
+08218A00198E00298600198E00109600427900218A00218A00218A00218A00318200427900427908
+427908198E00198E00218A00198E0000000000000000000000000000000000000029860000D70000
+9E00009E0000E30000E30000000000E7000000000000000000005265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600089600089600
+089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442414284
+8284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2
+CEFFFFFFD6D2CED6D2CE0896000896000896000896000896005265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E600000000000000000000000000000052
+65E65265E65265E600000000000000000000DF0000DB00089A0029860000000000000000000000C2
+0000000000000000000000000000DB0000C20000000000000000AA00089A003A7D003182003A7D00
+318200009E0000AE0000DB0000000000000000BE0000000000A20000DB0000A20000AA0010960010
+960010920000BA0000000000DB00009E0000AE0031820000AA0000CE0000000000A200218A002986
+0008960010920000B20000A60000AE0000C60000000000000000000000AA0000A20000C60000AE00
+089A00009E0000AA0000C60010960000A600218A00089A0000B600089600199200000000198E0021
+8A00198E00218E00218E00089600198E003182003A7D003182004A75085A71103182004279002986
+00318200109200109600000000218A00218A00109600199200218A002986002986000000003A7D00
+3182004279007365196B69197365197B71217B79217B75217B7D217B71217B71217369197365196B
+69103182003A7D004279004279000000003182004279083182003A7D000000000000004279083A7D
+003A7D004A75083182003A7D003182003182003182004A7508298600427908318200427908527108
+5A6D107B6D217B75217B69217B65195A6D105A6D105271084A75084279084279083182003A7D0031
+8200298600298A002986003A7D002986003A82003A7D003182003A7D00298600298600218A003182
+00318200298600318200298600298600298600298600218A00218A003A7D00218A00318200000000
+000000FFFF00FFFF00000000000000199200298600298A00218A003182002986003A7D003A7D003A
+7D002986003A7D00427900318200218A00089A00199200089A0042790019920000DB000000000000
+0000000000CA0029860029860000BE00009E0000D20000DF0000DB000000000000005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008960008
+9600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2
+CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CE
+FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896005265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000000000E3
+0000B600000000000000000000000000000000000000009E0000AA0000BE00298600427900427908
+29860000C60000AA0000A20000000000000000B20000B20000A60000A20000BE0008960000000000
+9E0000BA00109600218E003A7D00218A00427D0010960000CE000000000000000000000000000000
+00000000089A0010920042790029860010920000000029860000BE0000B20010960000B200109200
+00000000000000BA0000A20008960000D70000A20000DB0000CE00000000000000089A0000AE0000
+9E0010960000BE0000AE0000C60000C200089A0008960000B20000B20000B200109200009E0000BA
+00000000198E00198E00218A00109200199200218E00218A00198E003A7D002986007365195A6D10
+4A75085275084279083182003182003A7D00199200000000218A001096001092003A7D00218A0029
+86002986000000003A7D005A71105A71106B69197365197B75217B6D217B7D217B7D217B7D217B79
+216B69197B75217B79217B75217B71214279084279003182003182000000000000003182003A7D00
+0000003182004A75083A7D003182003182004A79084A79084A75083A7D005275083A7D003182004A
+75084279084A75085A6D105A71107365197365196369107365195271084A75083A7D003182002986
+004A75083A7D004A75083182003182003182003A7D003A7D003A7D002986003A7D004279003A8200
+3A7D00218A002986003182004279083A7D003182003A7D00218A00318200089600218A0029860029
+8600318200000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000218A00218A00218A003A7D
+002986004279004279004279083A7D004A7508427900427900318200199200009E00198E0000B200
+00B200089A001992000000000000000000000000003A7D00198E0000B20000D70000AE0000D20000
+00000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E6089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142
+D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896
+000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+00000000000000DF0000BA0000B600009E0000B60000BA0000C600000000000000000000009E0000
+CA00089A00218A00318200298600298600198E00218A003182004A7908218A003182002986001096
+0000DB0000BE0000000000D20000A600009E0000AA00089A0000BE0000C60008960000C600000000
+00000000E30000000000E70000000000C20000BE0000000000000000000000000000000000AE0008
+9A003A7D00109200218E00109200000000198E00298600198E0000AE00009E0000B60000000000D7
+0000AA0000B20000D200109200089A0008960000BE00009E0008960000AE0008960000C600089A00
+08960000A60000B200000000109200109600198E00218E00109200009E00198E00198E00218A0042
+79005A71106B69196B69196369107365194A7508427900089600199200427900000000218A00198E
+00109200109200298A002986000000003A7D00636D106B69197B69197365197B71217B71215A7110
+7B82297B82297B82297B79217B79217B79217B7D217B75217B75213A7D002986003A7D0031820042
+79080000000000004279000000003A7D007365193A7D004279083A7D003182003182002986003182
+003182004279004279003A7D004279084279005275085A7110636D106B6919636D10736519736519
+4279083A7D003182003182003A7D003182002986004279003182003182002986003182003182003A
+7D004A75083A82003A7D003A7D00218A003A7D003A7D00218A002986002986002986003A8200218A
+00218A001992001096002986004A7908000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000
+218A002986003182003182002986003182004279083A7D003A7D003182003A7D0031820029860029
+86003A820029860000BA0000AA0000C20000AA0000CA00000000000000000000000000218A00218E
+003A7D00198E0000D200089A000000000000005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E6089600089600089600089600089600089600089600089600089600D6
+D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CE
+D6D2CE0896000896000896000896000896005265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E600000000000000E70000D20000B20000DF0000B20000C60000BA0000B6
+0000D200089A00000000009E0000A60000AA0000C60000CE00009E00109200198E00089A0000B600
+00D700089A0000A200089A00089600089A0000000000DF0000BE0000D20000C20000B60010960000
+AE0000DB0000A20000000000D20000BE0000BE0000000000A60010960000000000000000C60000A2
+00009E0000000000000000A20000AA0029860029860042790000000000BE00218E0029860000AE00
+00D700009E0000C60000000000D200009E0000CE0010960000C20000BE00009E0000C200089A0000
+A20000D200089A0000A20000AE0000A60000000000000000B600109200218A00199200198E00198E
+00089A003182004279005A71107B6D217B6D217B69217365196B6919636D105A6D10000000000000
+000000000000000000000000198E002986003A7D002986000000003A7D006B69107B71217365197B
+75217B86297B86297B8629848A297B82297B82297B79217B7D217B79217B71216369105271084279
+084279083A7D003A7D004A7508427D000000000000003A7D004279003182004279084279003A7D00
+4279004279004A79082986003A7D003A7D004279084279004279005A6D105A6D10636D107B651973
+6519636D105A6D10636D105271103A7D005A71104A75084279004279084A75084A75083182003182
+003A7D004279004279084A7908427D003182003A7D003A82003182003A7D004A7508427900298600
+2986002986002986003182003A7D00089600298600318200000000FFFF00FFFF00FFFF00FFFF00FF
+FF00FFFF00FFFF00FFFF00000000218A003182004A75083182002986003182004279003A7D003182
+00198E00198E00218A00089A002986005271083A7D004A75083A7D00089A00109200218A00000000
+00000000A600000000089A0000AE003A7D000000000000000000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896000896000896
+00089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284
+424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFF
+FFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896005265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E600000000000000DF0000BA0000B200198E00
+109600109600218A00089A00198E0000A60000AA0000000000000000000000000000000000E30000
+CE0000CE00009E0000E30000E30000DF0000E30000E30000E30000AA0000000000000000000000DB
+0000D20000E70000CA0000DB0000B20000DB0000000000E30000BA0000000000C20000AE0000B200
+000000009E0000D70000C20000BE00109200000000000000198E003A7D00298A0010960000000000
+BE00318200218A0000A200109200009E0000000000DB0000D20000C600009E0000BE0000C60000C2
+00009E0000CE0000C60000BE0000AE0000AE0000BE00000000000000000000009E0000BE00089A00
+198E00198E00218A000896002986003A7D005A71107365197369197B75217B752173691973651973
+65195271080000003A7D00218A00198E00000000109200000000218A000000000000003A7D004279
+006B69197369197B71217B8629848A298C8E298C8E299492297B82297B79217B7D217B71217B7121
+7B71217B65195A71104A75083182003A7D00318200298600427900000000427D003A7D003182004A
+79084279004279004279084A75083A7D005275083A7D005275084A75083A7D004279005271085A6D
+107365196B6910736519736519636D10736519636D104279005A6D105A6D105A6D105A6D10527108
+5271085A6D10636D105271084279003182002986004A75084279004A75083A7D003A7D0031820052
+71084279083A7D003A7D00318200298600427D00298600218A00198E00298A00318200000000FFFF
+00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000004A7508318200318200318200318200
+5A71104279084279004A75085271083A7D00218E00009E00199200318200298A005A711052750863
+6D106B6919198E000000005265E60000000000000000000000000000000000000000005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600
+089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6
+D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000
+E70000D700218E004279006B69193A7D0010960000AA000000000000000000000000000000000000
+0000000000000000000000E70000E30000E30000DF0000E700000000000000000000000000000000
+00000000E30000000000000000000000000000000000000000000000000000000000E30000000000
+9E00009E00298A0000000000000000AE0000A600109200298600218A0000000000DB0000BE0000B2
+00198E00198E00000000009E0000A20000000000000000000000000000000000DB0000C60000A600
+10920000BE0000CE0000DF00089A00009E0000C60000C20000CE0000CE00000000009E0000A20010
+960000B200089600218A00109200109600198E003A7D003A7D005A71106B69197B6D217B71217B69
+217B71217369195A6D10427D006369100000003A7D00218A00218A000000003A7D00000000000000
+109600298A003182004A75086B69107B71217B75218C8E29949229949629949229949229848A297B
+7D217B7D217B75217B69217365197365197365194A75083A7D004A75083A7D003A7D000000003182
+004279004279003182003A7D003A7D005275085A71105A6D10527108636D104279004A7508427900
+5A7110427900636D106B69196B69107B69197365197365197B71215A6D10736519636D106369107B
+65196B69107365197365195271086369105A6D107365195A6D103182003A7D005275084A75083182
+004A79084279004A75085271085275083A7D003A7D004A75084A79084A79083A7D00298600298600
+2986002986004A7508000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000003A7D003A7D0031
+82004A7508427900427900636D105A6D105A71107365195A6D10636D103A7D00198E0000D200198E
+0010920000AE00198E003A7D0000A200218A004A75080000000000005265E6000000000000000000
+0000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E6089600089600089600089600089600089600089600089600089600D6D2CED6D2CE8482
+84424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000
+00000000000000FFFFFFFFFFFF000000000000000000000000000000FFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008
+96000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E600000000000000E70000CE005275087B6D2129860000A600000000000000000000
+00000000000000DF000000005265E65265E65265E600000000000000000000000000E30000000000
+E30019BA4A19BA4A00E30000DF0019BA4A318E9C19BA4A00E30000E3000000000000000000000000
+0000E30000000000000000000029860000C60000000000DB0000B2004A7508298A00218A00218E00
+00000000B20000C60000D200199200089A0000000000D70000000000D20000000000C60000B60000
+B60000B60000DF0000AA0010920000CE0000D20000CE0000CE00089A00089A00009E0000C6000000
+00000000009E0008960000B200009E00109600199200198E00089A00198E002986003A7D007B6519
+6369107B71217B71217B75217B6D217365194A75085A7110000000298A00427D0042790031820000
+0000218A00218A00000000318200218A00218A003A7D006B69197B71217B7D21848A299492299492
+298C8E29949229848A297B79215A71107B7121736519636D105271084279083182003A7D00318200
+318200218A000000004A79084A75084279002986003A7D004279087365196B69107B6D217B65197B
+6D217B65196B69104A75086B69105275085A71107B69197365197365197365196B69107B69217365
+197365196B69197B6D217365197365196B69107365196B6919636D107365195A71105A6D103A7D00
+6B69106369104A75083A7D002986002986006B69194A79084A75084A75085271084A75083A7D003A
+7D003A7D00218A002986002986002986003A7D00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+000000003A7D003A7D00427900318200318200427908527108427D004A7508736519636D107B6D21
+52750829860008960000D70000AE0000BA00009E0000D20031820000000000C60000000000000000
+00000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E6089600089600089600089600089600089600089600089600
+089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442414284828442
+4142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF0000
+00FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFF
+FFD6D2CED6D2CE0896000896000896000896005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E600000000000000DB00198E00218A00089A0000
+CE000000005265E65265E65265E60000000000005265E65265E65265E65265E65265E65265E65265
+E600000000000000000000000000000000000000000000000000000000000019BA4A00E700000000
+00000000000000000000000000000000000000CA0000000000C20000C60000000000000000AA0010
+9200089A00218A0000B20000DB0000000000C20000C600089A00109200089A0000000000BE000000
+0000D70000B600009E0000D20000BA0008960000BE0000C60010920000A20000DB0000B20000CA00
+00A60000C60000000000A200089A0000B200009E00009E005A6D10527508318200109200198E0029
+86002986003A7D007365197369197B71217B71217B7121736519636D104279082986000000000896
+003182004A7908318200000000218A00218A00000000218A002986003182003182005A6D10736919
+7B71217B82217B86299492298C8E299C9A297B7D217B79217B71217B71217365197B651973651942
+79082986002986003A8200218A000000004A75084A75083A7D003182003182003A7D007365197B71
+217B79217B71217B6D217365195A6D105271084279005271085A6D107B69197B71217B71217B7521
+7B71217B75217B79217B71217365197365197B6D217B6D217B71217B65197365197B69197B691973
+65195275085271085A6D107B6D217B65194A7508427908318200527508636D10636D107365195271
+084A75084A75084279004279003182003A7D00298600218A00298600298600427900000000000000
+FFFF00FFFF000000000000003182003182003A7D004A75084A79085A71100000000000004A790842
+79003A7D005A71107B71215A6D105A6D105A6D103A7D0000A20000BE0000DF0000E7000000000000
+000000000000000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008960008
+9600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2
+CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF
+FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFF
+D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896005265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000AA
+0000DB0000CA0000E30000A6000000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000
+00000000000000000000005265E600000000000000E30000DF0000000000DF0000000010920000AA
+0000000008960000AE00009E00198E00198E0000DB0000000000AA0000AA00089A0000D200000000
+00000000E30000B60000000000AA0000BE0000CE0008960000A20000A60000A20000D200089A0000
+B20000A20000BE0000AE00089A0000B20000000000A20000B20000C6004A75084A75087B71217B82
+21736519298600198E003A82003A7D003182006B69196B69197B6D217365197365197365195A6D10
+5A71103182003182000000001096002986006B6919000000198E000000001096002986003A7D0029
+86004A79085271107B69217B79217B82217B8221848A29848A298486297B7D217B75217B71217B6D
+217B69215A7110527108318200218A00218A003182000000004279004A75083182003A7D00427908
+4A75085271087B75217B86297B82217B6D216B69197365194A7508636D107365195A71105A6D1073
+69197B75217B7D217B79217B7D217B79217B7D216B69197B71217B75217365197B71217B71217B71
+217B71217B69217B71216369104A75085A6D106B69197B69197365195A6D10527508527108527108
+5271085A6D10636D104A7508636D10636D104A75086B69104A75083A7D004279084A75083182003A
+7D006B69194279004279000000000000003A7D004A75084279003A7D004279003182000000000000
+00FFFF00FFFF000000000000000896003182005271104279001092003A7D00636910736519427900
+08960000CE000000000000000000005265E65265E60000000000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E6089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CE
+FFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF00
+0000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E60000000000000000000000000000000000000000000000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E60000000000005265E600000000000000000000000000000000E700
+00000000BA0000000000BA0000000000CE00109600089A0000C60000C20000D20000B60000000000
+BA0000B60000000000000000000000BA0000DB0000000000CA0000AA0000DB00009E0008960000A6
+0000BA0000D700089A0000AA0000BA0000B20000BA0000000000000010960000B20000B20000CE00
+4279087B65197B7D218C92297B75212986003182002986004A79083A7D005A6D107365197B69217B
+69217365197B65195A7110427D004A7508199200000000198E00198E00000000089A00218A000000
+000896002986003A7D002986004279085A71107365197B71217B7D217B86298C8E297B82217B8221
+7B79217B75217B6D217365195A7110636910527108298600000000000000000000298A002986004A
+75083182003182003182003A7D007B69197B75217B86297B71216B69197B69217B65195A6D107365
+19736519636910636D107B71217B7D217B82297B7D217B7D217B79217B7D217B7D217B75217B7121
+7B71217B71217B71217B75217B6D217B71217365197365195A71107B69197B71217B71217B712142
+79004A75085271085A6D107B65195A6D106369105A71105271105271085271086369105271084279
+004A75084279005275084A7508636D104A75087365195271085271107365196B69197B6519636D10
+5A7110000000FFFF00FFFF00000000000000FFFF00FFFF0000000000A20000AE0000BE0000C60000
+9E00198E005A71105275083A7D00089A0000B6000896000000000000000000000000005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E6089600089600089600089600089600089600089600089600D6D2CED6
+D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF00000000
+0000000000000000FFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF
+000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE
+0896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E60000000000000000005265E60000005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000052
+65E65265E600000000000000000000DF0000DF0000DF0000BE0000D70000BA00009E00089A000000
+0000000000000000000000000000000000000000DF0000CE0000000000000000000000BE0000DB00
+00A20000CE0000C60000B60000A60000CE0000BA0000B20000AE0000000000000000CA0000000031
+820010960000A200109200198E006B69107B69216B69104279001096003A7D004279005271085A71
+107B69217B71217B6D217B7121736519636D105A6D105A7110736519736519318200000000000000
+218A00109600089A00000000089600298600218A004279005271086369105A6D107365197B71217B
+7D217B82217B82217B79217B71217B6D217365196B6919527110427D00427900000000298A003182
+000000002986004A75083182003182004A75084A79085275087B71217B75217B7D21736519636D10
+5275087365196369107365195A6D106B69197B69217B82297B8229848A297B86297B86297B82297B
+7D217B7D217B7D217B75216B69197B75217B71217B71217B6D217B71217365197B69196B69108C92
+297B82217B86297365195A71107365196B69107365197B65197365197365195A7110636D10527108
+5A6D105A6D105275085275085271085271085275087365197B65195A6D107B65195A71107365197B
+6D217B75217365197365195A6D10000000000000000000FFFF00FFFF000000000000000000003A7D
+0000A60000D200009E0000E70000D20000D700009E00298600000000000000000000000000000000
+0000000000005265E65265E60000000000005265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896000896000896
+00089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142
+848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFF848284FFFFFF848284FFFFFF848284FFFFFF848284FFFFFF848284FFFFFF848284FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF0000
+00FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF
+FFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6
+D2CEFFFFFFD6D2CED6D2CE0896000896000896000896005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E600000000000000000000DF0000E30000000000DF0000000000BA0000BA00
+00CA0000BA0000DF0000000000A20000C60000B60000E70000AE0000000000BE0000000000BE0000
+000000D20010920000B60000AA0000A60000B20000BE0000AE0000BE0000AE000000000000000000
+0000AE0000000000B20000D20000CE0000A600109600198E005A6D10427908218A00298600298600
+4279004A75085271105A6D106B69107B6D217B71216B69197369195271083182003182007365197B
+7121089A00218E00000000218E00109200000000198E00109600318200218A003A7D005A71104279
+084A75087365197B71217B7D217B71217B71217B6D217369197365196B69195271084279084A7508
+000000218E00198E00000000298A002986003182003A7D003182003A7D0042790842790052710863
+69106B6919636910636D105A6D105271085A6D106369107B65197B69197B7D21848A298C8E298C8E
+29848A297B86295A71107B82297B82297B75217B7D217B75217B79217B75216B69197B75217B6D21
+7B69217B71218C8E299C9A298C8E299C96297B69197369197365197365196B69106B69196B69196B
+6910636D107B65196B69197365197B65195A6D107B65197365195A6D10636910636910636D107B69
+216B69197365197B69217B71217B6D217B6D217B7521000000000000FFFF00FFFF00FFFF00FFFF00
+FFFF00FFFF0000000000000019920000C600298600298600089A0000DB0000E70000E30000000000
+00000000000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600
+089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6
+D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF
+FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000FFFFFFFFFFFF0000
+00FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2
+CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E600000000000000000000000000000000000000
+E30000E70000000000B60000BE0000C60000B20000000000B20000B20000CA0000E30000AA000000
+0000000000E30000DF0000CA00000000000000000000000000000000000000000000000000000000
+00000000D700089A0000C60000000000C60000DF0000A20000BA003A7D004A75084A75085275084A
+79084279003A7D004A79085271086369107B69197B69196B69197B69217B71217B71216B69194A75
+08298600218A00298600198E00009E00000000218A00218E000000001096003A7D00318200218A00
+2986003A7D003182003A7D005271086B69197B69217369197B6D217365197B71217369196B69195A
+6D10000000000000000000198E003A7D00198E000000002986003182004A79084279083A7D005275
+085271106369107365197365197B6D215A71105A6D106369105271087B65196369107B6D217B7D21
+848A29A59A31A59E31A59E318C8E29848A297B82297B79217B82297B7D217B82297B79217B79217B
+75217B79217B79217B7921848A297B86299C9629A59A31CEC6197B82216B69197365197365197B69
+197B71216B6910636D107365196B6910636D106B69197B6919636D106B69197365197B6921736519
+6B69197B6D217B65197365197365197B69197B69197365197B71217B7D217B7D21000000000000FF
+FF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000000000AE0000B60000C20000BA001096002986
+0000C20000BE000000000000000000005265E60000005265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E6089600089600089600089600089600089600089600089600D6D2CED6D2CE8482844241
+42D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008
+96000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000000000
+0000000000E70000DF0000000000000000000000C20000CE0000B60000000000000000AA0000BE00
+00D20000C20000000000000000000000E30000E70000000000DF0000B60000D20000E70000E30000
+AA0000BE0000E70000E70000000000000000000000000000C200000000089A0000A60000AE003A7D
+00736519427900636D105A6D107365197B65197365197B75217B71217365197B6D217B6921736519
+7B71216B69195A6D105271083A7D001992001092004A7908298600000000089A00000000218A0019
+8E00218A002986003A7D003A7D00427900427900298600527108527110636D107B65195A6D107365
+19636910736519636D104A7508218A000000003A7D003A7D00198E00000000218A00298600427900
+3A7D002986004279085A6D107365196B69107B6D217B651973651952710852711052711052711073
+65197B69217B7D21949229BDB229C5BA21ADA631A59E319C9A299492297B86297B86297B79217B82
+217B7D217B7D217B7D217B79217B79217B7D217B8629848A29949229949229A59A31A59A317B7521
+7B6D217B69217B6D217B6D217365197B69197B71217365197B69217B6D217B69197B65197B6D217B
+69217B6D217B69197365197B6D217369197365197B69217365197B71217B75217B7D217B75217B79
+217B7521000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000527110298600
+089A00089A0000C20000CE0000AE0000E3000000000000000000000000000000005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E6089600089600089600089600089600089600089600089600
+D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
+000000000000000000000000000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000000000000000000000FFFFFFFFFF
+FFFFFFFF000000000000000000000000000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2
+CED6D2CE0896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+0000000000005265E600000000000000DF0000DF0000E30000000000000000E70000CA0000CA0000
+000000C20000D20000C20000CE0000000000000000000000E70000E30000DF0000000000AA000000
+00009E0000BA0000C200000000000000000000000000009E0000B20000B20000A20000A600089600
+00000000B20000A600218A002986007365196B69197B71217B69197B69217B6D217B6D217B75217B
+71217B6D217B6D217365197B69215A6D105275084A7508318200109200109200089A001092000000
+00000000218E00218A00198E003A7D003182005275085275084279004279003A7D004279005A6D10
+3182004279005275083A7D004A75085A71104A75083A7D004A7508000000089A00089A0000000000
+0000298600298A002986004A75083A7D005271086369107365196B6910736519736519636D106369
+105A6D106B69106B69197B6D217B69197B7D21BDB621E6DF10D6CE19D6CA19ADA231CEC619949229
+848A297B82297B82297B86297B86297B86297B82297B82297B79217B82297B86298C8A298C8E299C
+9629848A297B82217B7D217B71217B69197B71217B6D217B69217B6D217B69197B69197B69217365
+197369197365197B6D217B65197B69217B6D217365197369197369197B75217B6D217B75217B7121
+7B7D217B71217B7D217B71217B7D21000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+FF00000000218A0000DB0000BE0000E70000E70000DF0000B60000C2000000000000000000000000
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008960008960008
+9600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482
+84424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CE
+FFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E600000000000000000000000019BA4A00E30000DF0000E30000DF000000
+0000CA0000E30000E70000000000E30000E30000CA0000000000E30000E30000E30000E30000E300
+00E30000000000000000E30000000000000000000000BA0000CA0010920000AE00009E00009E0000
+9E00198E00089A00000000089600109200109200089A004A75087365197365197365197B71217369
+197369197B71217B79217B71217B75217369197365197365195A6D10427908199200109600009E00
+109600009E00000000000000000000218E00318200218A005A71104A7508736519636D107B71216B
+6910427900427D003A7D003A7D00427900318200427900298600000000000000000000000000089A
+00198E00198E00000000318200218A002986004A7508427908527508736519736519736519527108
+5A6D105271106B6919527108636D10636D107B69197B69217B7D217B8229B5AA29EFEB08EFEB08E6
+E310BDB621A59E319C96298C8E29848A29848A29848A297B82297B86298C92297B79217B82297B82
+297B82219492299492299492297B82217B7D217B75215A71107B75217B75217B6D217B6D217B6919
+7365197365197365197B71217365197369197B6D217B6D217B6D217B6D217B71217B75217B75215A
+71107B71217B75217B69217365196B69197365197365197365197B6D21000000FFFF00FFFF00FFFF
+00FFFF00FFFF00FFFF000000004A7508199200218A00089A00427900089A00218A003A7D00109600
+00D7000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896
+00089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFF
+D6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896005265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000019BA4A00E30000E300
+00E30000DF0000DF0000000000DF0000DF0000000000DF0000CA0000E30000000000DF0000E30000
+DF0019BA4A00E30000E70000000000CA0000B20000DB0000CE0000A200009E0000B60000A60000AE
+00109200109200198E00318200298600318200198E00000000109200089A003A7D005A7110636910
+7B69197B69217B71217B79217B75217B75217B75217B69217B71217365196B6919636D106369106B
+691900BE0000BE0000AE00109600000000000000000000109200298600218A002986003182006B69
+196369107365197B7121636910427908427908318200318200298600198E00218A00218A00000000
+089600109600109600089600109600000000109200198E00298600298600427D0052750842790052
+71085271084279084A75084279004A7508527108636D107365196B69197B69197B75217B75219496
+299C9A29AD9E31BDB229ADA629F7F700A59E319C96299C9A298C8A298C8E298C8E299496297B8629
+7B86297B7D217B86297B86298C8E29848A299492299C96297B86295A71107B79217B71215A71107B
+75217B69217B71217B75217B6D217B71217B6D217B71217B71217B71217B79217B7D217B71217B7D
+217B71217B7D217B71217B71217B6D217B69217B69216B69196B6919636910736519427908527110
+000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000006B69107B69194279003A7D0029860029
+860000AA0000D20000C60000000000DF0000E3000000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E6089600089600089600089600089600089600089600D6D2CED6D2CE84
+8284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600
+0896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000005265E65265E600
+000000000000000000000000E30000000000000000000000DB0000000000DF0000DB0000CA000000
+00000000000000318E9C19BA4A00E30000E30000000000E70000BE0000D70000DB0000CA0000B600
+089A0000CE0000D20000CA00109600089A00427D00527108636910427900000000199200198E0010
+96004A75086B69197369197B6D217B71217369197B75217B69217B71217B69217B71217365197365
+196B691952750852711052750800C20000BE0000BE00000000000000000000218A0000BE00109600
+198E002986001096006369105271087365197B6D216369104A7508318200218A0029860010960021
+8A00298600000000109600089A00109600109600089A00000000198E00089600218A00427D002986
+002986003A7D00427908427D004A75083A7D004A7508527108527108636D106B6919636D107B6919
+7B6D217B75215A7110848A29949229A59E31A59A31F7F700DED710A59E31949229DEDB109C96298C
+8E298C8E298C9229848A29848629848A297B82218C8E29848A298C8E298C8E298486297B86297B79
+217B7D217B6D217B6D217B75217B75217365197B71217B71217369197B6D217B75217B79217B7921
+7B6D217B7D217B7D217B7D217B79217B79217365197B71217B69216B69196B69197365195A6D105A
+6D10636910427900218A005A6D10000000000000FFFF00FFFF0000000000000000DB004279083A7D
+0000BA0000B20000B60008960029860010920000BE00000000198E000000005265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896000896000896
+00089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284
+424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFF
+FFFFD6D2CED6D2CE0896000896000896000896005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E600000000000019BA4A00000000E30000000000000000E30000DF00000000000000
+00DF0000CA0000000000000000E300318E9C00000000E30000DF0000000000C20000BA0000E30000
+DB0000C200089A0000B60000AA0000BE0000A20000B20000A600218E005A6D106369107B69193A7D
+00000000218E005271085275087B6D217B71217B71217B69217365197365197365197B69217B6D21
+7B71217369197369196369105A6D10427900318200089A0000B20000BE0000BE0000000000A60000
+B20000AE00109600089A00198E00198E00218A004279083A7D005A6D106369106B69193182002986
+00298600218A003A7D00218A00198E00000000089A001096003A7D00089A00000000089A003A7D00
+199200318200298A003182003182003182004279005271084279004A75083A7D005271085271085A
+6D10636D106369107365197B71217B75217B79218486299C96298C8E29CEC619A59A31A59A31DED7
+109C96298C8E299C96298C8A299C96298C8E29848A298C8E29848A29848A299492298486298C8E29
+848A298C8E297B82217B7D215A71107B7D217B71217B75217B75217B75217B71217B71217B71217B
+75217B75217B6D217B79217B79217B79217B82297B82297B75217B6D217369197B69217369197365
+19636910636D104279084279084279007365193A7D00009E00109200198E00000000000000089A00
+00D20000B6000896006B6919198E0000BA0000DF0010920010920000CA00000000000000089A0000
+00005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600
+089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6
+D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFF
+FFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896005265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E600000000000000E30000E30000000000000000DF0000
+E30000DF0000000000000000000000000000DF0000000000000000000000DF0000000000DF000000
+0000000000B60000AA0000DB0000C60000AE0000BA0000D70000BA0000A60000AE0000AE00089600
+4A75087365194A7508000000089600198E002986003A7D006B69197365195271085A71106B69196B
+69197B6D217B6D217B6D217369196B69196369107365194279083A7D00218A00089A000896000896
+0000000000C20000A20000AA00198E00089600109600109200089600198E003182004A7508427900
+4279004279003182004A7908298A00218A00218A00218A00198E00199200000000198E0000000000
+0000000000089A00198E00198E002986003A7D003182003A7D002986004279083A7D004279003A7D
+003A7D004279005A7110736519636D107365197B6D217B6D217B79217B6D217B82218C8E299C9629
+949229A59A319C96298C8A298C8E298C8E298C8E299492298C8E299492298C8E29848A299492298C
+8E29848A298C8E298C9229848A29848A297B86297B86297B79217B82297B79217B79217B79217B79
+217B75217B75217B79217B79217B71217B75217B79217B8229848A297B86297B79217B75217B7921
+636D107B65196B69196B69105A71104279083A7D003A7D00198E00427900636D1031820000CA0008
+9A00198E0000B60000CE0000BE0000D20000BE0000AE0000C20000B20000CA0000BA0000B60000CA
+00000000089A0000AE000000000000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E6089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2
+CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246BFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008
+96005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000000000
+0000000000E30000E70000DF0000000000000000E30000E3000000000000005265E6000000000000
+00DF0000C20000000000D70000E70000000000000000AA0000A20000DB0000B60000BE0000AA0000
+A20000BE0000BE00218E003182003182004A75080000003A7D004279005A6D105271084279083182
+003182006369105A6D107365197B6519636D107365197365196B69196B69195A6D105A71104A7908
+318200298600089A0010920000000008960000A60000A60010960010920010960010960029860019
+92004279083182004279084A75083A7D003A7D00089600298600218A003A7D00198E003A7D000000
+00000000000000000000218E00298600089600198E00198E002986001096003A7D003A7D00298600
+4A75085A71104A75083A7D004279004A75085275087365196369107B69197B75217B75217B75217B
+82297B82217B8221848A299496299C9A298C8E29848A29848A297B8221848A29848A29848629848A
+298C8E298C9229848A298486298C8E298C8E29949229848A29848A297B86297B86297B82297B7D21
+7B7D217B7D217B75217B71215A71107B75217B75217B79217B7D217B7D217B79217B82297B862984
+86297B82217B7D217B75217B7D217B71217365197B65195A7110318200218E0000BE0000CA0000A2
+002986004A790800AA00089A00318200089600009E0000C60000A20000CA0000DF0000DF0000AA00
+00CE0000B200009E0000000000000000000000A6000000005265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E6089600089600089600089600089600089600089600D6D2CE
+D6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2
+CE0896000896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E60000000000005265E600000000000000E30000E30000000000000000DF0000000000000052
+65E600000000000000000000000000000000A60000C200009E0000A60000E7000000000000000000
+00000000000000009E0000CE0000A60010920000A600298A00198E000000001992005A71107B6519
+7B71217B65193A7D003A7D00218A003182005271105A7110527110636D105A6D105271105271106B
+69194A75083A7D00298600427900298600218A00109600000000000000009E00009E0000A20000AA
+0010960000B200218A00198E002986003182004279084A7508318200318200198E003A8200199200
+198E00109600199200000000000000198E00298600109600199200198E00198E002986002986003A
+7D003A7D003A7D004A75083182004A75083A7D004279004279004279085A6D106369106B69197B6D
+217B71215A71107B82217B86297B82217B8221848A298486298C8E298C8E297B82218C8E299C9A29
+848A297B8221848A29848A29848A298C8E298C8E298C92298C8E298C92298C8E298486298C8E297B
+82218C8E298C92297B82297B79217B7D217B79217B75217B75217B75217B79217B7D217B75217B79
+217B82297B86297B86297B7D217B79217B75217B6D21636D107B7921736519636D100896003A7D00
+00D20000D20000C200089A0000B20010920000D70000B20008960000AE0000AE0000D20000D70000
+D70000AE0000DF0000BE0000E30000DF000000000000005265E60000000000000000005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008960008960008
+9600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241
+42848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0824
+6B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08246B08246B08246B08246B08246B08246B
+08246B08246BFFFFFF08246BFFFFFF08246B08246B08246B08246BFFFFFF08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246BFFFFFF08246B08246B0824
+6B08246BFFFFFFFFFFFFFFFFFFFFFFFF08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246BFFFFFF08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFF
+D6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896005265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E60000000000000000005265E600000000E70000E3000000000000
+0000000000000000000000000000000000000000D70000E30000000000000000000000D20000CA00
+00DB0000C20000E30000E30000D200089A00000000009E0000BA00009E0008960000BA0029860000
+00003A7D006369107B71216B69196369102986003A7D002986004279004279084279003182004279
+085A6D104A75084A7508089600298600298600198E00198E00198E00218E00298600009E0000A600
+000000089A0000A60000B20000A600109200198E003A7D00298600318200318200298600218A0029
+8600089A00198E00198E003A7D00089A00000000000000218A00218A00089A003A7D00199200198E
+00318200298600218A002986003A7D003182003A7D004A75083A7D00527508427900427908527110
+736519636D105A6D107B6D217B75217B75217B79218486297B82217B8629848A299C9629848A298C
+8E298C8E298486298C8E29848A297B8221848A298C8E29848A298C92298486298C8E298C8E298C8E
+29848A297B8629848A299C96297B82217B82297B86297B82297B7D217B7D217B7D217B6D217B7921
+7B7D217B79217B79217B82299496297B86297B79217B7D217B7D217B6D217B69217B6D2173691973
+65197B6919298600009E0019920000B20000CE0000B60000E70000B20000B60000CE001992002986
+003A7D00089600109200009E0000AA0000DF0000E30000E3000000000000000000000000005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896
+00089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CE
+D6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84
+8284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF08246B08246B08246BFFFFFF08246B08246B08246B08246BFFFFFF08246B08
+246B08246B08246B08246B08246B08246BFFFFFF08246B08246B08246BFFFFFF08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+FFFFFF08246B08246B08246B08246BFFFFFF08246B08246B08246BFFFFFF08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246BFFFFFF0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246BFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6
+D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E60000005265E6000000000000000000
+19BA4A0000000000005265E65265E600000000000000000000CE0000CE0000B20000B600089A0019
+8E0000000000000000000000000000C20000CA0000D20000BA0000DB0000DB0000000000CE0000B2
+0000AE0000A200000000109600218A00318200298600318200318200318200427900198E00298600
+318200318200427D002986003182003A7D00109600109600089A00198E00089A0000C20008960063
+6D106B691929860000A60000000000B20000BE0000A200089600218E00218A00109600298600427D
+00298600318200089600199200198E00089A00089A00218A00000000198E00000000218E00218E00
+1992003A7D00199200218A00198E00298A00218A003A7D002986002986002986003A7D00427D0042
+7D004279084A7508527108636D106B69197B69197B69197B71217B7D217B82297B82217B86297B86
+297B82217B8221949229848A297B82217B82297B82217B82217B82217B8629949229848A29848629
+8C8E29848A29848629848629848A298C8E297B8629848A29848A298486297B86297B82297B82297B
+7D217B7D217B75217B79217B75217B79217B82297B86297B86297B86299496297B75217B79217365
+197B7121636910636D104A75085275083A7D004A750800B20000AE0000E30000E300000000000000
+00E700009E00298600198E00218A0000CE00218A0000B20000AA0000DF0000000000000000000000
+00005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E6089600089600089600089600089600089600089600D6D2CED6D2CE84828442
+4142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFF
+FF848284848284848284848284848284848284848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000
+0000000000000000000000FFFFFFFFFFFFFFFFFF08246B08246B08246BFFFFFF08246B08246B0824
+6B08246BFFFFFF08246B08246B08246B08246B08246B08246B08246BFFFFFF08246B08246B08246B
+FFFFFF08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246BFFFFFF08246B08246B08246B08246BFFFFFF08246B08246B08246BFFFF
+FF08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246BFFFFFF08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600
+0896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E60000000000000000000000000000005265E6000000000000218E0000B200218A0000BE
+00009E00089A003A7D003A7D00089A0000000000B60000000000000000C20000BE0000A20000DF00
+00000000000000B20000A60000D20000CA00000000109200089A00089A000896003A7D00198E0031
+8200318200109200009E00199200218E00198E0000B60008960000BE00198E0000BE00218A001096
+0000A20000C600009E00636D10527508198E00000000009E0000C60000A20000AE00109200298600
+298A00318200298600318200427D00089600198E00089A00218A00089A00089A00000000089A0008
+9A00000000089600198E00089A003A7D00298600109600298600298A003A7D00218A003182003A7D
+00427900427908427D004279004A75084279004A75087365196369107B6D217B71217B75217B7521
+7B7D217B82217B82217B82297B8229848A297B86297B82217B7D217B7D217B7D217B82217B82217B
+82217B82217B8221848A298C8E298C8E29949229949229848A29848A29848A298C8E297B82217B82
+219496297B7D217B82297B7D217B7D217B79217B7D217B79217B7D217B82297B86297B86297B8221
+7B82217B82297B75217B75217365197365195271104A79083A7D005A711008960010920000D20000
+000000000000000000E30000000000000010920000AA0000B60010920000A60000BA0000BE0000DF
+000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896000896000896
+00D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142
+FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF08246B08246B08246B
+FFFFFF08246B08246B08246B08246BFFFFFF08246B08246BFFFFFFFFFFFFFFFFFF08246B08246BFF
+FFFF08246BFFFFFF08246BFFFFFFFFFFFF08246BFFFFFF08246B08246BFFFFFFFFFFFFFFFFFF0824
+6B08246B08246BFFFFFFFFFFFFFFFFFF08246B08246BFFFFFF08246B08246B08246B08246BFFFFFF
+08246B08246B08246BFFFFFF08246B08246B08246BFFFFFFFFFFFFFFFFFF08246B08246BFFFFFFFF
+FFFF08246B08246BFFFFFFFFFFFFFFFFFFFFFFFF08246B08246BFFFFFFFFFFFFFFFFFF08246B0824
+6BFFFFFFFFFFFF08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6
+D2CED6D2CE0896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E60000000000000000000000000000005265E600000000CA00
+00B600089A0008960000BA00527508427900198E0031820000000000B60000BE0000C600009E0000
+0000000000000000000000009E0000000000AE0000BA0000B60000000000AA00009E0010960000C6
+00109200109200218E0010960010920000BA0000A60000A60000AA0010960010920000A600109600
+00CE00089A00109200009E0000C60000AA0000A6004A7908198E00009E0000000008960010920010
+92001092002986003182003182003A7D00298600298600298600089A00089A00218E00198E00218A
+00000000000000218A000000000000001992003A7D00198E003A7D00198E003A8200298600198E00
+218A00218A002986004A75085A6D104279003A7D005271084A75085275084A75086B69107B712173
+65197369197B7D217B79217B79217B7D217B82217B86297B7D217B86297B82217B82219496297B7D
+217B75215A71108C8E297B82217B82218C8E297B82217B8629848A298C8E29848A29848629848629
+848A29848A297B86297B86297B86297B82297B79215A71107B82297B79217B79217B7D217B75217B
+82299496298486298486299C96297B82297B79217B75217365197B65197B6D214A75081092001092
+00218A0008960000AA00109600009E0000000000000019BA4A00000000AE0010920000CA0000B200
+4A750842790000B6000000000000000000005265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600
+089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84
+8284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF
+FFFF08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08246B08246BFFFFFF08246B0824
+6B08246BFFFFFF08246BFFFFFF08246BFFFFFF08246BFFFFFF08246B08246BFFFFFF08246BFFFFFF
+08246B08246B08246BFFFFFF08246B08246B08246B08246B08246BFFFFFF08246BFFFFFF08246B08
+246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFF08246B08246B08246BFFFFFF08246B08246B0824
+6BFFFFFF08246BFFFFFF08246B08246BFFFFFF08246B08246B08246BFFFFFF08246BFFFFFF08246B
+08246B08246BFFFFFF08246BFFFFFF08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2
+CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896005265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E60000000000005265E60000005265E652
+65E600000000000000BE0000AA0000BE0000C600218A00298600089A0000BE0000000000000000CA
+0000A20000A600089A0000AE0000AA0000000000AA0000000000000000000000000000000000D200
+00BE0000A200009E0000A600009E00109200089A00218E0000BA0010920000AE0000B20010920000
+A60000AE0000CE0000AA0000CA0000A200089A0000AA0000A60010920000B20000BE0000BE000000
+0000C60000BE00109200089A00089A002986003182003182003A7D00318200427900218A00198E00
+089A00109200009E000000000000000000000000000896003A7D003A7D00089600198E00198E0019
+8E00298600198E00199200198E00218A004A75082986002986005275083182005271084279004279
+084279007365197B69217365197B71217B79217B71217B7D217B82217B7D217B7D217B8221848629
+7B82217B82217B86297B79217B75218486297B82217B7D217B79217B86297B86297B8221848A297B
+8629848A298C8E29848A298C8E297B82218C8E298486297B7D217B82297B7D217B75217B7D217B6D
+217B71217B7D217B75217B82298486297B86297B82217B82217B75217B69217365197365194A7908
+4A750873651942790000C60000A20000A20000D70000BA0000000000000000000000000000000000
+000000D70000AE003A7D00009E0000A200218A000000000000005265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E6089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFF
+FFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF848284000000
+000000000000000000000000848284FFFFFF848284FFFFFF848284FFFFFF848284FFFFFF848284FF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF08246B08246B08246BFFFFFF08246B08246B08246B08246B08246B
+08246BFFFFFF08246B08246B08246BFFFFFF08246BFFFFFF08246BFFFFFF08246BFFFFFF08246B08
+246BFFFFFF08246BFFFFFF08246B08246B08246B08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFF
+FF08246BFFFFFF08246B08246B08246B08246BFFFFFF08246B08246B08246BFFFFFF08246B08246B
+FFFFFF08246B08246B08246BFFFFFF08246BFFFFFF08246B08246BFFFFFF08246B08246B08246BFF
+FFFF08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08246BFFFFFF08246B08246B08246BFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896005265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000
+005265E65265E65265E65265E600000000000000CA0000E30000BA0000000000BA0000B600089A00
+00000000B60000E700089A00089A00218A00198E0000A20000D20000000000C60000AE0000000000
+000000C60000000000DB0000BA00009E0000AA00218A00198E00009E00089A00218A00109600089A
+00109200009E0029860000A20000C60000D20000BE0000A20000DB0000B60000B20000A20000AA00
+00B20000000000000000000000A600109600109200089A0029860029860029860031820029860031
+8200298600218E00089600089A00089A00089600000000000000089A00109600089A003A7D000896
+00000000000000000000000000198E00109200198E00427900218A00298A00427D00318200318200
+4A75085A71104A79084279005A6D106B69197B6D217B65197B71217B75217B79217B75217B7D217B
+79217B75217B79217B79217B86297B8229848A29848A297B82299496297B75217B79217B75217B7D
+217B79217B86297B82217B82218486297B8221848A297B8221848A297B86299496297B79217B8221
+7B75217B7D217B7D217B71217B75217B7921636D107B7D217B82217B7D217B86297B79217B7D217B
+71215A7110298600318200298600089A00298600198E0000AE0000CE0000E70000DF000000000000
+0000000000000000000000000000DF0000AE0000A60000BE0000D2000000000000000000005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E6089600089600089600089600089600089600D6D2CED6D2CE
+848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFF
+FFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08246B08246B08246BFFFFFF08246B08
+246B08246B08246B08246B08246BFFFFFF08246B08246B08246BFFFFFF08246BFFFFFF08246BFFFF
+FF08246BFFFFFF08246B08246BFFFFFF08246BFFFFFF08246B08246B08246B08246B08246BFFFFFF
+08246B08246B08246BFFFFFF08246BFFFFFF08246B08246B08246B08246BFFFFFF08246B08246B08
+246BFFFFFF08246B08246BFFFFFF08246B08246B08246BFFFFFF08246BFFFFFF08246B08246BFFFF
+FF08246B08246B08246BFFFFFF08246BFFFFFF08246B08246B08246B08246B08246BFFFFFF08246B
+08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896
+000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E600000000E30000000000E30000000000
+E30000BE0000BA0000000000000000000000CE0000D70000000000000000CE0010960000CE000000
+0000A200218A0000000008960019920000000000A20000BA0000C6001096004A79085271103A8200
+089A00109600298A00736519298600198E00198E00009E00009E0000A200009E0000A20000D20000
+DF0000D70000D70000000000000000A20000AE00198E0000B600199200199200218A003A7D004A75
+083A7D004A75083A7D00218A00218A00198E00089A00109200000000000000000000000000199200
+089A00089A00198E00000000000000298600318200089A00089A003A7D00198E003182003A7D0029
+8600427D004A79085275084279005A71105275084A79085271086369107B69217B69217365197B79
+217B75217B79215A71107B7D217B7D217B79217B82217B8221848A29848A299492297B82217B7D21
+7B79217B75217B75217B75217B7D217B7D217B7D217B86297B86297B8221848A297B82217B82217B
+86297B79217B82217B75217B7D217B79217B7D217B71216B69197B69217B6921636D107B75217B7D
+217B79217B79217B79217B71217B6921089A0019920000C60000B20000B60000A200009E0000BA00
+00E30000E30000000000000000000000000000000000000000000000DF0000000000000000000000
+00000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008960008960008
+9600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241428482
+84424142FFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000
+0000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08246B0824
+6B08246BFFFFFF08246B08246B08246B08246B08246B08246BFFFFFF08246B08246B08246BFFFFFF
+08246BFFFFFF08246BFFFFFF08246BFFFFFF08246B08246BFFFFFF08246BFFFFFF08246B08246B08
+246BFFFFFF08246BFFFFFF08246B08246B08246BFFFFFF08246BFFFFFF08246B08246B08246B0824
+6BFFFFFF08246B08246B08246BFFFFFF08246B08246BFFFFFF08246B08246B08246BFFFFFF08246B
+FFFFFF08246B08246BFFFFFF08246B08246B08246BFFFFFF08246BFFFFFF08246B08246B08246BFF
+FFFF08246BFFFFFF08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CE
+FFFFFFD6D2CED6D2CE0896000896000896005265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFF00
+00000000000000000000D20000BA0000D20010920000000000BE0000000000AA0000A20000C60008
+9A004A79084279083A7D00000000000000000000000000109200198E00198E0000C200009E0000CE
+00009E0000DB0000DB0000DB0000B60000B60000000000AA0000A600009E00109200218A00009E00
+298600218A003182002986004A75083A7D00298600298600198E00198E0008960010960000000008
+9A00000000218A00089A00199200000000000000218A00198E00089A00218A00218E00198E002986
+002986002986003182003A82003182004279083182003182004279004A75084A75085A6D106B6919
+7B6D217365197369197B71217B7D217B75217B75217B75217B7D217B7D217B82297B8221848A298C
+8E29848A297B82217B79217B75217B75217B71217B79217B79217B79217B82217B86297B79217B86
+298486298C8E297B82217B86297B7D217B79217B75217B7D215A71107B71217365197369196B6919
+7B69217B71217B75217B7521636D107365197B69217B69216B691931820029860000A20000A20000
+D700089A0000D20000E30000E30000DF000000000000000000000000000000000000000000000000
+00000000000000000000089A000000000000005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896
+00089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE
+D6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF84828484828484828484828484
+8284848284848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF08246B08246B08246BFFFFFF08246B08246B08246B08246B08246B08246B08246BFF
+FFFFFFFFFFFFFFFF08246B08246BFFFFFF08246BFFFFFF08246B08246BFFFFFF08246BFFFFFF0824
+6B08246BFFFFFFFFFFFFFFFFFF08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFF08246BFFFFFF
+08246B08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFF08246B08246B08246B08246BFFFFFFFF
+FFFFFFFFFF08246B08246BFFFFFF08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFF08246B0824
+6BFFFFFFFFFFFFFFFFFF08246B08246BFFFFFF08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFF
+FFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896005265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E6000000000000000000000000318E9C0000000000005265E6000000000000FF
+FF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000B600198E00089A0000000000C6000000000000
+0000C60000BA0000B20000A60000000000000000000000000008960000B600000000000000218A00
+10960000AA00089600009E00089A0000A20000D70000A20000B20000000000DB00009E0000CE0000
+9E0000A600218A003182002986003A7D002986004A75083182003A82002986002986003A7D00198E
+00089600000000089600000000218A00109600109200198E00000000218A00199200109200218A00
+089600109600198E003A7D003182003182003A7D003182003A7D004279003A7D003182003182003A
+7D00636D107365197B6D217B69197B69217B69216B69197B7121636D107B79217B7921636D107B7D
+215A71107B8629848A298C8A298C8E297B79217369197B6D217369197B6D21636D107B79217B7921
+7B7D217B79217B7D217B82217B82217B82297B82217B86297B86297B82297B7D217B79217B71217B
+75217B6D217365197B69217B71217B6D217B75217B71217B7521736519736519736519636D105A71
+103A7D003A7D0029860000D70000E70000CA0000DF0000DF000000000000000000000000005265E6
+0000005265E60000000000005265E65265E60000000000000000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E6089600089600089600089600089600089600D6D2CED6D2CE848284424142D6
+D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246BFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E60000000000000000000000000000000000000000005265
+E6000000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000000000198E00298600
+3A7D0000000000D20000000000AE0000C200000000000000218A00009E003182000896003A7D0010
+92001092003A7D0000000000A200009E00218A0000CE0000D20000C60000D70000D20000000000D7
+0000CE0000A60010920000A20000A600109600089A002986002986003A7D00427900298600298600
+298A00218A00109600089A00000000000000000000109200089A00198E0000000000000010920019
+8E00198E00218E00089A001096003A7D003182001096002986004279003182003182004279002986
+00218A00218A004A75084279005A6D107365196B69197B69217369197B69217365197B75217B7121
+7B71217B79217B71217B75217B7D217B79218C8E297B82217B75217B6D2173691973651973651973
+65197365197365197B75217B71217B79215A71107B7D217B82217B86297B82217B82217B86297B86
+297B7D217B86297B86297B75217365197365197365196369107365197B69217B6D217B71217B6921
+7365196B69197B65196B69194279003A7D00218A0000DB0000AE0000CA0000E30000000000000000
+00000000000000000000005265E65265E60000000000000000000000000000000000000000005265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600089600D6D2
+CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6
+D2CE0896000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E600000000000000000000E30000BE00109200
+0000000000005265E6000000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF
+FF00000000000000318200000000198E0019920000000000000000000000AA0000A6000896001092
+005271084A7508198E0000A200198E00089A0000AA0000000000000000000000BE0000CE0000B200
+00CE0000B60000000000AA0000A20000AA0000A60000B200089A00198E003A7D00198E00198E0031
+82002986002986002986002986003A7D00198E0000000000C200000000218A00198E002986000000
+00000000009E00198E00298600109600218A00109600298600198E00198E00218A00109600298600
+2986003A7D003A7D00218A003182002986003182004279005275087365197365196B69197B692173
+65197365197365197B6D217B71217B71217B79217B75217B7D217B75217B7D217B71217B71217B6D
+217B6D217B69217B69217B69217B71217B69217B71217B71217B6D217B71215A71107B79217B8221
+848A29848A29848A29848A298C92297B79217B79217B69216369107365195271104A75085A6D1063
+6D105A6D104279085A6D106B69197B71216B69105A6D103A7D003A7D00009E0000B20000DF000000
+000000000000000000000000000000000000000000000000000000000000000000005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600089600
+089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442
+4142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFF
+FFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896005265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000
+DF0000CE0000C2000000000000005265E6000000000000000000000000FFFF00FFFF00FFFF00FFFF
+00FFFF00FFFF00FFFF00FFFF0000000000000000000000000000A60029860000000010920000BE00
+00AE00089A00198E00218E00218A00298600089A003A7D0010920000C20000A20000DF0010960000
+000000000000C20000D70000CE0000000000AE0000A20000C60008960010920000A200089600198E
+00089A00198E002986003A7D003A7D00198E00089A00298600199200000000000000089600000000
+3A7D00198E00000000109600109600218A00198E00218A00218A00218A00298600298600198E0021
+8A00218A00298600298600218A003A82002986003182003A7D00298A003182005A71105271085A6D
+107365197369197365197B6D217B69217B6D217B6D217365197B6D217B7521636D107B79217B8229
+7B6D217365197B69217365197365197B69217B69217B69217B69217B69197B6D217369197B71215A
+71107B75217B7D217B7D21848A298C8E298C8E299C9A297B7D217B7521636D105A6D103A7D003A7D
+004279004279083A7D005A711029860000BE00009E00218E004279087365194A7508218A00009E00
+00D70000D20000000000E3000000000000000000000000005265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E6089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2
+CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFF08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B0824
+6B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B
+08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08
+246B08246B08246B08246B08246B08246B08246B08246B08246B08246B08246BFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+D6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E60000000000000000000000000000000000005265E600000000CA0000B60000A20000CA00
+000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000218A003A7D0000000000000000000000
+B20000000000C20000DB00109200298600298600298600218A00218A00218E0000C20000CA0000CA
+0000D70000DB0000CE0000000000BE0000000000C20008960000000000B20000C60000C20000C600
+00B200298A00199200198E00198E00218A0029860031820031820019920019920019920000000000
+00000896000000001096003A7D0000000000A600109200089A00298600198E00218E00218A00298A
+00198E00298600198E00198E00318200318200298600318200318200218A00298600298600298600
+3182004A7508636D105A71105A6D107365197B69197365197B69217365197B6D217B6D217B71217B
+71217B79219496297B6D217B69216369106369106B69107B65195A6D10636910636D107369197B69
+217B69217B69217B71217B6D215A71107B7D217B7D217B82217B82217B75217B71217365197B6D21
+5271105271104279002986003182004A79083182006B69105A7110198E00218A0000D70000C60010
+960029860000C20000C60000BE000000000000000000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E6089600089600089600089600089600D6D2CED6D2CE848284
+424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896
+000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000
+D20000B20000D700009E00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000009E0000AE
+0000DB0000C60000000000000000BE0000D20000BE00218A00218A00089600198E00109200298600
+218A0000AA0000D70000D20000000000000000000000E70000AA0000000000000000000000BE0000
+CE0008960000C200109600009E0000BA00109600198E00198E00298600218A00218A00089A00198E
+00218A00000000198E0000BE00000000427900089A0000000000AA0000A600218A00199200427900
+218A00218E002986003A7D00089A00089A00199200198E00218A00218A002986003A7D0029860021
+8A00298A002986003182004A7908318200427D005A6D105A71107B65196B69197365196369107B71
+217B65197B69217365197B75217B75217B71217B69217365196B69197369195A6D10527110527108
+7365197365195A6D107365196B69197B71217B69217B71217B75217B79217B82217B82217B75217B
+6D217369196B69196B6919636D102986003A7D00218A002986004A75085A71105A71107B6D215A71
+10109600198E0000BA0000CA0019920000BA0000CA000000000000000000005265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E608960008960008960008960008
+9600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241428482844241
+42FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFF
+D6D2CED6D2CE0896000896000896005265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E600000000000000C60000D20029860029860000AA00198E00000000000000FFFF00FFFF00000000
+00000000D20000000000AE0000000000000000CA0000D700089A0000A200198E0010920029860010
+9600089A0000C600198E0000CE0000DB0000C60000000000000000BE0000000000000000BE000000
+0000000000A20000A20010960008960000C60000A60000A20000B200298600199200218E00109600
+218A0000BA0008960000BA00198E00000000089600009E00000000009E0000D20000000000CE0000
+B200089600089600218A00218A00218E00218A00218E00109600198E00199200218A00218A002986
+00298600198E00198E00199200318200318200427900318200218A003182005275087365195A6D10
+7365196B69106369107365197B69216B69197369197B6921736519736519636D107B651973691963
+6D10636D10636D105271085A71105271085A6D106369107365197B69217365197B6D217B79217B7D
+217B7D217B7D217B7D217B71216369106369104A7508527110427D003A7D00298600318200298600
+298600636D107B69214A7908198E00318200089A0000DF0000E30000000000000000000000000052
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896
+00089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE
+848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6
+D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896005265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E600000000000000C600218A00109200298600427900198E00198E0021
+8A0000000000000000000000000000000000000000000000000000AA0000000000000000DB0000B2
+0000B600298A00109200298600089A0000000000000000A20000000000000000E70000E70000BE00
+00BE0000000000BA0000CA0000000000CE0000DB0000A200089A00109200198E00198E0000B20019
+8E00218A0000BE00218A00198E00089A00089A00000000000000218A0000DB000000000000000000
+0000000000000000CE0000B200089A00218A00218A00218A00218E00089A00198E00199200218A00
+089A00298600198E00218A002986003A7D00198E004A75085A6D103A7D003A7D0029860042790829
+86003A7D004A7508736519636910636D10736519736919636910636D106369106369106B69196369
+105A6D104279003A7D005A71107365195A71104A75084A75085275084A75085271085A6D10736519
+7B71217B6D217B75217B75217B79217B7521636D10736919636D105A71105A6D104A750842790831
+8200218A00218A00198E00198E0029860052710842790019920000DB0000C20000E3000000000000
+000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E6089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFF
+FFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000FF
+FFFFFFFFFF000000000000000000000000000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E6000000000000000000000000089600218A00198E
+003A7D0000BE0000D70000B200089A0000DB0000A20000B600089A0000DB0000000000AA0000AA00
+00AA0000000000000000D20000CE0000CE0000D200089A0000000000BE0000BE0000000000000000
+BE0000D20000BE0000BA0000000000B60000AA0000CA0000000000BA00009E0000B200009E0000A2
+00089A00009E00109600089600089A00109600089A00089600009E0000A60000000000CE0000B600
+00000000000000000000AA0000A60000AA0000DF00089A00218E00199200218A00218A0029860029
+86003182003A7D00089A00199200199200198E00427900198E001092002986003A7D004A75083A7D
+003182002986002986002986003182003182004279005A6D105A6D107365195A6D10736519636910
+4A75087365197365195A6D103A7D00318200089A001992005271083182005271084A750842790852
+75084A79085271086369107365197369197B71217B7D215A71107B82297B75217B71217B75216369
+106369105A71103182003A7D00198E00198E00218E00318200218A0052710800B20000C2003A7D00
+0000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600D6D2CED6D2
+CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08
+96000896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000
+00000000000000000000C20000C20000A60000D20000DB0000000000000000000000000000000000
+000000000000AA0000AA0000C60000000000000000000000000000000000000000000000000000E3
+0000E30000BE0000BE0000E30000E70000BA0000000000000000BE0000BA00089A0000000000A600
+00A60000C60000CA00089A0010960000BA00198E0010960000AA0000A60000A60000B60000D20000
+000000A20000DB0000000000000000A60000AA0000C20000A60000A600089A00009E00218A00218A
+00198E00089A00218E003A7D003A7D00199200109600109600109200298600298600198E00318200
+427900527108527508298600427D00198E00198E00198E00199200198E004279004279005271105A
+7110636D105A71105A6D104279005A6D103A7D004A75083182003A7D00198E00218A00218A002986
+004279084A75084279003A7D003A7D005271106B69197365197B69216B69197B7D217B75217B7921
+7B7D217B75217B7121736519636D10427908298A00218A0000A200009E0000A20010920000AE0042
+79001992000000000000000000000000005265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600089600
+089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442414284
+8284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF
+FF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2
+CEFFFFFFD6D2CED6D2CE0896000896000896005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E600000000000000000000000000000000DB0000000000000000000000C6
+0000AE0000000000000000000000AA0000AA0000AE0000A60000000000CA0000D70000B20000B600
+00CE00089A0000000000C20000E30000CA0000BA0000BE0000CA0000000000000000C20000E30000
+BA0000000000B20000BE0000D70000A20000BE0000B200218E0000D20000D20000C20000AE0000B6
+0000A20000000000000000B60019920000000000000000DB0000AA0000A60000A20000C60000A200
+00AA00199200199200198E00198E00109200218A00218A00198E00198E00198E00109200089A0019
+9200089A003182004279083182004A7508298600218A00298600109600198E003A7D00199200218A
+004279005275085A71105271086369105271084A7508318200318200298600298600298600298600
+427D002986003182003A7D003182004279002986003182003182005A71107365196B69197B692173
+65197B75217B75217B79217B7921636D107B6D215A6D10636D103A7D0010960010920000AE0000D2
+0000C20000AE0000D20000B600009E0000E3000000000000005265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E6089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2
+CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF
+FFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CE
+FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896005265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E600000000000000000000000000000000000000000000DF00000000
+00000000D70000DF0000000000000000A20000AA0000000000AE0000AA0000AA0000AA0000000000
+CA0000B60000D70000AE0000D700009E0000000000BA0000CA0000CE0000BE0000BA000000000000
+0000CA0000BE0000D20000000000000000C200089A0000B20000B200089A0000AE0010960000D200
+00BA0000B60000D200009E0000000000C60000CE0000D700089A0000000000C60000A20000B20000
+C60000A60000AA0000AA0000A600218A00109600198E00218E00218A000896000896003A7D003A7D
+00198E00199200199200198E003A7D00318200318200427D00427D00318200318200089A003A7D00
+198E00298600198E00198E002986004279004A75085A71105271104A750831820029860029860029
+86003A7D00298600198E00198E003A7D003A7D002986003A7D002986003182003A7D003182006369
+107B71216B69197B71217365197B69217365197369197B75217B7921736919636910527110298600
+089A0010920000BA00009E0000BA00009E0000CE0000C60000DB000000000000005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E6089600089600089600089600D6D2CED6D2CE848284424142
+D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000000000000000000000
+FFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF00
+0000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896005265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E600000000000000000000000000000000000000000000
+D70000BE0000C20000D200109600009E0000000000AA0000DB0019920000AE0000000000000000AA
+0000AE0000AA0000000000C60000A200009E0000AE0000DB0000D700089A0000000000CA0000D200
+00CE0000000000CA0000000000000000000000000000000000000000BA0000BE0010960000B20008
+9A0000CE0000AA0000B60000CA0000000000000000000000B20000D70000000000000000000000BE
+0000B60000B20000D200089600009E00089600089A00089A0000BA00009E00089A00089A00000000
+000000298600198E00089A00218A00298600089A00198E00318200218A002986003A7D0029860031
+8200089A003A7D00198E00198E00218A001992003A7D00198E003182004279004279003A7D004A75
+08318200298A003A7D00636D105275083A7D00427908218A00109600198E003A7D00318200218A00
+218A00198E00218A0073651900AE0000CA003A7D00009E006B69195A6D107B69217B79217B82217B
+86297B7521527108298600089A0000CE0000AA0000A20000CA0010920000D20000D70000CA000000
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600089600089600D6
+D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FF
+FFFF848284FFFFFF848284FFFFFF848284FFFFFF848284FFFFFF848284FFFFFF000000FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+00FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CE
+D6D2CE0896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000E3
+0000000000000000000000AE0000C20000C60000AA00089A0000000000BA0000BA0000D20000DF00
+00DB0000D20000000000000000AA0000AA0000AA0000000000D20000CE0000A20000DF00009E0000
+9E0000000000D20000C20000000000000000E30000CA0000CA0000CA0000D20000D20000000000CE
+0000A20000A200109200009E0000AE0000DB0000B60000000000B20000B20000B60000C60000D700
+00000000A200009E0010960000B20000AA00009E0000C60010920010960000BE00089A0000BE0019
+8E00000000000000000000000000198E00218A00089A00298600218A00089A003A7D003182002986
+003A7D00298600298600218A003A7D00089A00109200298600218A00198E00089A00198E00199200
+218A00298600427900427900089600218A005271084279003A7D00218A00218A0000BE0000B60019
+8E00198E00089A00218A001992004279004A7508427900318200218A0000A2003A7D000896002986
+005271107B71219496298C92297B82297B7521527508318200009E0000D20000CA00009E00089600
+00D70000A6000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896
+00089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284
+424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF
+FF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF000000000000000000000000000000FFFFFFFFFFFF000000FFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFF
+FFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+00000000000000000000000000000000000000B60000DB0000BA0000C20000000000000000AA0000
+A20000D70000B20000AA0000CE0000D70000000000000000DB0010960000AA0000000000B60000DB
+0000B60000DB0000CE0000D70000000000000000000000E70000CA0000000000CA0000CA0000E700
+00BA00009E0000000000B600089A0000AE0000C20000C20000CE0000C60000000000BA0000AE0000
+CE00009E0000000000000000AA00109200218A0010920010920000A60000A60000B20010960000C2
+00109200000000000000000000218A00089600199200218E00218E003A8200218A00089600298600
+3182001992003A7D00427900298600298600089600198E001096001096003A7D00318200218A0019
+9200198E00089A00198E00199200218A00218A003A7D001992001992003A7D004279004279083182
+0010960000DB00198E0029860010920000BE0000BE0000A600009E003A7D00218E0000DB0000CA00
+3A7D0010920000AE004279007365197B8229CEC6199492297B7D217B7D212986003A7D00089A0000
+E30000DF0000C60000C2000000000000000000005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E6089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6
+D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896005265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E600000000000000000000000000000000CA000000000000000000000000000000
+0000000000C60000B20000DF0000BE0000C60000AA0000B20000000000AE0000B60000C600089600
+00BA0000000000AE0000BE00009E0000D20000C60000D70000000000D20000E70000E70000000000
+E30000CA0000DB0000E70000BE0000BA0000000000B60000CE0000D70000AA0000CE000000000000
+0000C200089A0000D70000DB0000000000000000000000A20000CE0019920008960000A200009E00
+109200089A00218A00198E00218E00000000218A00089600218E00198E00109600109600218A003A
+7D00318200218A00198E00298600318200318200298600199200318200089600218A00198E001992
+003A7D00000000109200298A00218A000896003A7D00298600218A00198E00089A00318200109200
+1096003A7D005A6D1031820010920000BE0000A200198E0010960000B20000A60000A20000D20000
+BE0000C20000AE0000CE0000A60000CE001992004A75083A7D007B71217B8229CECA19848A297B79
+2131820000AE0000D70000DF0000E7000000000000000000005265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E6089600089600089600089600D6D2CED6D2CE8482
+84424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000
+00000000000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFF000000FFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFF00000000
+0000000000000000000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008
+96005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E60000000000005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E600000000000000000000000000000000BE00
+00BE0010960000000000D70000D70000B600089600089A0000A20000DB0000A2003A7D0000000000
+CE0000D70000D20000D70000BA0000000000AA00009E0000C60000D70000BE0000000000E70000D2
+0000CA00000000089A0000E70000BA0000BA0000C20000E30000000000000000AE00089A0000C600
+00AE0000000000D700089600009E00089A00199200089A0000000000DB0000B20000000000000000
+000000000000000000B600318200198E00218A004A75083A7D00000000089A00089A00089A000896
+00198E00218A004279083A7D001096003A7D00198E00198E00318200298600427900089A00198E00
+198E00318200089600089600000000218A00218E00089A00218A00198E003A7D00198E0008960010
+960029860029860000A200198E00218A00427908298600089A00009E0000A20000AA0000C20000C6
+0000C60000B60000CE0000D70000DF0000BA0000BA0000B600009E00198E0000A600009E006B6919
+848A29D6CA19DED7106B6919318200089A0000CA0000C20000000000E3000000005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600089600
+089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442414284828442
+4142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFF
+FFD6D2CED6D2CE0896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E60000000000000000000000005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000
+000000000000D70000C200009E0000BE0000DB0000000000000000000000000000000000C60000C6
+00009E00089A00000000009E0000C60000BA0000BA0000C20000DF0000000000CA0000BA00000000
+00000000E70000E30000D20000E30000000000CE0000CA0000E70000CA0000CA0000D20000DB0000
+000000000000000000000000000000000000000000C60000D70000C20000D70000000000D70000D2
+0000BA0000AA00089A000896002986003A7D00000000000000000000000000000000000000109600
+198E00109600199200218E001096003A7D003A7D00218E00298600427908198E0029860031820021
+8A003A7D00089600298600089A00109600198E00000000318200218A00218E00109200198E00218A
+00089A00089A0000A600218A00109200218A00198E0000BE0000BA0010960042790010920000AA00
+00AE0000CA0000AA0000BA0000BE0000B20000A20000B20000D70000BE0000BE0000E30000E70000
+DB00218E004279007B71218C8E29FFF700B5AE297B7521736519198E0000A6000000000000000000
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E6089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2
+CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFF
+D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896005265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000
+E3000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000
+0000000000000000E30000000000BE0000A600009E0000D70000C600109200089A0000C20000A200
+00000000B60000000000B20000000000000000AE0000AA0000A60000AA0000CA0000E30000E30000
+000000CA0000000000C20000CA0000D20000D20000CA0000DF0000000000000000CA0000CA000000
+0000000000000000000000000000A60000000000000000000000000000CA0000CA00089A00000000
+00000000C20000AE00009E0000A60000AE003A7D00427D002986003A7D0029860000000000000010
+9600218A00000000000000000000000000000000218A00198E00109600198E00198E003A7D003182
+00318200427908298600198E004A750829860000BE00199200218E00000000000000218E00198E00
+10920010960010960000BA0000A20008960000A200198E00199200198E00198E00009E0000A20000
+AE00218A0019920000D20000AA0000BA0000D70000B600089A0000BE0000C60010960000BE000000
+0000000000000000BE0000000000AA0000C6005A6D107B7D21CEC6198C8A29736519636D10218E00
+00C2000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E6089600089600089600089600D6D2CED6D2CE848284424142D6D2CE
+FFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E600000000000000DF000000000000005265E65265E65265E65265E65265E6000000000000
+00000000000000000000000000DF0000DF0000000000D200000000000000009E0000D70000DB0000
+AA0000A20000B60000000000D20000C20000000000000000B60000D20000CE0000C60000A20000BE
+00089A0000BE0000E30000000000000000CA0000CA0000CA0000E30000E70000CE0000E70000E700
+00CE0000000000000000CA0000CE0000CE0000E70000D20000D20000000000BA0000A60000000000
+9E00009E00000000089A0000BA00089A0000B200218E00198E003A7D005271082986003A7D003A7D
+005A7110318200298A00318200199200218A000000003A7D00000000199200199200109600198E00
+089600198E003A7D003A7D003A7D003A7D0029860031820010960000BE00009E00089A0000BA0021
+8A0008960010960000B600009E00109200198E0000A600089A00009E0010960000AE001992003A7D
+0010960000B60000DB00009E0000AE0019920000D20000E70000BA0000BE0000BE0000AA0000AA00
+00BA0000000000000000E30000D20000BA0000BA0000000000000000DB004A75087B65197B79217B
+71216B691900BE0010920000D2000000000000005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E6089600089600089600089600D6D2CED6
+D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE
+0896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E600000000E30000E30000E7000000005265E65265E65265E600
+000000000000000000000000DF0000000000DF0000E30000B60000E70000AE0000E70000CA000896
+0000DB0000B60000DF0000B20000B200218E0010960000C60000A200009E0000AA00000000000000
+00000000D20000BE0000D20000B600089A0000000000000000DF0000E30000E70000CA0000CA0000
+E70000C20000E70000E70000000000E70000CA0000E30000C20000BA0000D20000B60000D2000000
+0000BE0000BA0000BA0000000000000000CA0000B60000BE0000AE00089A005275087365196B6910
+4A75082986004A7508298600636D104279004A79085271087365195A6D1052711031820029860008
+9A00000000000000000000298600199200000000298A003A7D00318200298600089A001092001092
+00009E0010920000BA00000000109600089600109600218A00089A0000A60000B20000B20000B200
+00CE00009E00009E00218A0010920000C60000AE0000AA0000000000000000000000000000000000
+BE0000BA0000E30000000000000000D20000E30000BA0000BA0000E30000CE0000BA0000D2000000
+0000BE004A75085A6D10636D103A7D0000CE0000C6000000000000005265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896
+00089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142
+848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6
+D2CEFFFFFFD6D2CED6D2CE0896000896005265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E600000000000000E30000DF0000E7000000
+000000005265E65265E600000000000000000000000000C60000CE0000BE0000C20000BE0000C600
+00000000AA0000B60000CA0000C20000D700109600009E0000BE00009E0000AA0000BA0000D70000
+DB0000B20000C60000DB0000DB0000000000000000C200089A0000A60000A20000E70000DF0000E3
+0000DF0000E30000E30000CA00089A0000E70000000000E70000E70000E30000D20000B60000BE00
+00AA0000000000000000E70000BE0000BA0000000000000000000000C20000C60000A20000B60031
+82007B6D217365194279003182002986004279005271085275083A7D007365194279005A6D10636D
+10636D10427900427900318200218A004A7508198E00000000000000000000000000000000298600
+198E0000B20010920000A20000A20000B20010920000BA0000000000B20010920019920029860000
+A20000BA0000A20000DB0000AA0000D70000CE0000DF0010960000000000000000000000DF0000DF
+0000E70000CA0000CA0000000000000000000000E30000CA0000CA0000E70000CE0000000000CA00
+00E30000DF0000E700000000089A0010920029860031820000DB0000000000000000000000000052
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E6089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6
+D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2
+CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896005265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000E700
+00DF0000E30000000000000000000000000000000000000000E30000DF0000C20000AA0000A60000
+BA0010920000CA0000C600000000009E0000CA00009E0000AE0000A200089600089A00089A001092
+0000CE0000DB0000000000CA0000B20000BE0000D70000000019BA4A19BA4A00000000BA00109600
+00000000DF0000E30000E30000E30000E30000DF0000DF0000000000000000E70000E70000AA0000
+E30000E70010920000E70000000000000000D20000E70000BE0000AA0000AA0000000000000000D2
+0000B20000B200218A003182003182003182004A75083A7D005271083A7D005A7110427908318200
+4279005275085271084279085271085A7110298600318200318200318200298600318200218A0042
+790029860000000008960010920000BE0008960000A20000A60000C20000A20000BA001092000000
+00109600109200218A0000BA0000A600198E0000C20000C60000D70000C200089A0000000000DF00
+00DF0000DF0000DF0000DF0000DF0000E70000E70000E70000E70000E30000E30000E70000E70000
+E70000000000000000000000DF0000E30000DF00000000000000000000009E0000A20000000000E3
+000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E6089600089600089600D6D2CED6D2CE8482844241
+42D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960052
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E600000000000000000000E30000E30000E30000E30000000019BA4A00DF0000E7
+0000CA0000DB0000D20008960000AE00009E0000AE0000000000A600109200089A0010960000A600
+109600298600218A0000BE0000AA0000C60000000000000000000000BE0000000000E30000E30000
+E30000DF0000000000000000E30000DF0000E30000DF0000000000000000000000000000000000E7
+0000DB0000E70008960000BE0000E70000BE0000B60000000000BE0000B60000B60000D20000E300
+00A60000000000C20000B60000B600109600198E00198E003A7D003A7D0042790073651952711042
+79004A75084279083A7D004A75085271085271087B65195A71105271085271082986003182005275
+08636D103A7D005A71103A7D0000000000000000000010960000AA0000C60000C60000C60000CE00
+00B20000A60000AA00000000198E00089600298A00318200198E0000AE00009E0000DB00089A0000
+B60000CA0000000000DF0000DF0000DF0000E30000E30000E30000DB0000DF0000DF0000E30000DF
+0000DF0000000000DF0000DF0000000000000000000000000000DF0000DF0000DF0000E300000000
+00000000000000E3000000000000005265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600089600
+D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2
+CED6D2CE0896000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E600000000000000E70000DF0000DF0000DF0000E300
+00000000DF0000DF0000BE00089A00089A0000CE0000D70000A20000D200000000009E0000C60000
+B200009E00218A0000C200009E0000A20000A60000BA0000B600000000000000FFFF00FFFF000000
+0000000000000000000000000000000000000000000000000000000000000000000000000000DF00
+00D20000CA0000000000E70000E30000BA0000AA0000D20000CA0000BA0000BA0000000000E70000
+E70000C20000AA0000DF0000CA00000000009E0000C600089A0000A20000BA00218A003A7D005275
+08636D105275083182003182003A7D003182005271084279085A71107365195A6D106B6919527110
+3A7D004A75084279004A75083A7D00427908318200318200000000198E0000B20000000000B20000
+A20000BE00089A0000CE0000AE0000A200009E0000000000000000B60008960031820010960000BE
+0000A60000AE0000BA0000BA0000000000000000E70000E30000E30000DF0000E30000DF0000DF00
+00DF0000DF0000DF0000DF0000000000000000000000000000000000000000000000000000000000
+DF0000DF0000E30000E70000DF000000000000000000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E6089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482
+84424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CE
+FFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000E30000DF0000
+DF0000CA0000E70000000000000000E70000E30000C20000B60000CA0000C20000D70000D7000000
+00009E0000D70000A60000A200009E00009E0000AA0000000000000000DF0000C600000000FFFF00
+FFFF00FFFF00FFFF00FFFF00FFFF0000000000000000E30000000000E70000000000E70000000000
+DF0000E70000000000BE0000BE0000000000000000000000000000E70000BA000000000000000000
+0000000000C20000BA0000E70000BA0000A60000D70000000000DB0000D70000DB0000B60000C200
+1096000896002986003182003182003A7D003182003A7D000000000000000000000000003A7D003A
+7D005275085A6D105271085271086369107365195271083A7D00198E00198E00109600089A000000
+00009E00000000009E0008960008960000B20000AE0010960008960000D20000000010920000A600
+19920029860000AA0000AA0000A20000B60000A60000000000E70000E30000DF0000DF0000DF0000
+E30000DF0000DF0000DF0000DF0000DF0000DF0000DF000000000000000000000000000000000000
+0000000000000000000000DF0000E70000E3000000000000000000000000005265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E6089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFF
+D6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000
+000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896005265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000FFFF
+00FFFF0000000000000000E700000000000000FFFF00FFFF0000000000000000A200009E0000D700
+00C20000CE0000D700000000089A0000AE0000A20000CE0000AA00000000000000FFFF00FFFF0000
+0000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000000000E30019BA4A0000
+0000E70000E70000E70000000000DF0000E30000000000DF0000000000DF0000DF00000000000000
+00000000D20000D20000E70000C20000B60000E30000E70000BA0000BE0000000000D20000C60000
+DB0000B20000AA0000A20000BA001992003A7D00298600298600298A002986003182000000002986
+004A79080000000000000000004279087365197365194A7508636D10736519427900198E00298600
+318200218E00000000218A00089A00089A0000000000AA0000DB00009E00089A0000B20010960000
+0000000000009E0000C200089A0000AA0000A20000C60000B20000000000000000000000E30000DF
+0000E30000E70000E30000E30000E30000DF0000E30000DF0000DF0000DF0000E30000E300000000
+00000000000000000000000000000000000000000000000000E3000000000000005265E65265E600
+00005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E6089600089600089600D6D2CED6D2CE84
+8284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF
+FFFFFFFF000000000000000000FFFFFFFFFFFFFFFFFF000000000000000000FFFFFFFFFFFF000000
+FFFFFFFFFFFF000000000000000000FFFFFFFFFFFF000000FFFFFF000000000000FFFFFFFFFFFFFF
+FFFF000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF0000000000
+00000000FFFFFF000000000000FFFFFFFFFFFFFFFFFF000000000000000000FFFFFFFFFFFFFFFFFF
+000000000000000000000000FFFFFFFFFFFF000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600
+0896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FF
+FF0000000000DB0000D70000CA0008960000000000000000C20000D70000D700000000000000FFFF
+00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+00000000E30000000019BA4A00E30019BA4A00E30000000000E30000E70000000000000000000000
+E30000E70000E30000000000000000CE0000CA0000E70000BA0000BA0000E70000BA000000000000
+0008960000BA0000BE00089A0000D70000CA0000A20000000000000000B600218A00009E003A7D00
+000000000000298600318200298600089A00000000000000218A00218A006369103182005A711052
+7108318200198E003A7D004A7908298600000000089A00089A00009E0000000000B20000AE0000AE
+00009E0000BA00089A0000CE0000000000DB0000C60000D70000A20000D200000000000000000000
+00DF0000DF0000DF0000E30000DF0000E30000E30000E30000DF0000DF0000DF0000DF0000E30000
+E30000DF000000000000000000000000000000000000000000000000000000000000000000000000
+005265E65265E60000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896000896
+00089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284
+424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFF
+FFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF000000000000FFFF
+FFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF0000
+00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFF
+FFFFD6D2CED6D2CE0896000896005265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF
+00FFFF00FFFF00FFFF00FFFF00000000000000000000000000000000000000000000000000000000
+00000000DF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00FFFF00FF
+FF00FFFF00FFFF00FFFF0000000000000000000000E30019BA4A00E30019BA4A00000000E30000E7
+0000E300000000000000318E9C00E30000DF0000000000000000000000DF0000E30000DF0000CA00
+00000000000000AA0000BE0000C20000D200089A0000B60000D70000CA0000AA0000000010920000
+00000000000000000000002986002986002986003A7D00198E00089A00109600000000218E002986
+00298600218A002986002986003A7D003A7D002986003A7D0029860000000010920000A200000000
+00D20000B60000AA0000AE0000AE00089A0000AA0000A20000000000D70000CE0000B60000AE0000
+CA0000000000E70000E70000E30000DF0000DF0000DF0000E70019BA4A318E9C19BA4A00E30000E3
+0000E30000000019BA4A19BA4A00E30000000000000000000000000000E300000000000000000000
+0000005265E60000000000000000000000000000005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E6089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6
+D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF848284FFFF
+FF848284FFFFFF848284FFFFFF848284FFFFFF848284FFFFFF848284FFFFFFFFFFFFFFFFFF000000
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF000000000000000000000000000000FFFFFF000000FFFFFFFFFFFF000000000000000000000000
+FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFF
+FFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFF
+FFFFFFFF000000000000000000000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000
+000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFF
+FFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896005265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00
+FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000E70000000000000000
+D20000BA00000000000000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+00000000FFFF00FFFF00FFFF00FFFF00FFFF000000005265E65265E600000000000000E300318E9C
+00E30000000000E30000E70000E30000E30000000000000000000000000000E30000E30000DF0000
+000000E30000000000000000CA0000C60000E70000BA0000DB0000DF0000C60000B60000D7000000
+0000000000D700109200298600218A00318200318200089600218A00318200218A00218A00198E00
+089A00218A000000000000003A7D00089A00198E00218A00089A00198E0000000000000000000010
+920000BA0000CE0000000000BA0000B60000BE0000BA0000BA00009E0000A200009E0000D2000000
+0000AE0000D70000AA0000000000000000000000E30000DF0000E30000DF0000E70000E70000E300
+318E9C318E9C00E30019BA4A19BA4A000000318E9C000000318E9C00000000000000000000000000
+00000000000000000000000000000000005265E60000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E6089600089600D6D2CED6D2CE848284424142D6D2
+CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFF000000FF
+FFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFF
+FFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000
+FFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFF
+FFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000FFFF00FFFF00FF
+FF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000
+000000000000005265E60000000000005265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00FFFF000000005265E65265E652
+65E600000000000000000000000000000000E30000E300318E9C000000000000000000318E9C318E
+9C00E70000DF0000000000000000000000DF0000DB0000DF0000E30000D20000AA00000000000000
+00000000000000000000D70000C20008960000BE00218A004A7508427900527508318200089A0019
+8E0010920000BE00009E00198E00199200089600218A000000000000000000000000000000000000
+00218A00009E00089A0000BE0000AA00109600009E0000000000000000DB0000CA0000A20000AE00
+00D70000A60000BA0000000000D20000C20008960000000000000000000000000000E70000E30000
+E30000E30000E70000E300318E9C318E9C318E9C318E9C00E3000000000000000000000000000000
+000000000000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E60000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600D6D2CE
+D6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000000000
+000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF
+FFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFF
+FF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000
+FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF00
+0000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFF
+FF000000FFFFFFFFFFFFFFFFFF000000FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2
+CE0896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FFFF00FFFF00FFFF00FFFF00
+FFFF00FFFF000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600
+0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000000000000000FFFF00FFFF000000000000
+005265E65265E65265E65265E65265E65265E65265E65265E6000000000000318E9C19BA4A000000
+000000000000318E9C318E9C00E30000E30000000000000000DF0000000000E70000000000000000
+000000000000B60000D70000BA00009E0000DB0000BA0000CE00089600089600198E002986006B69
+107B6D215A6D104A75084A790800BE00109600218A00198E00089600218A00298A003A7D00298A00
+318200089600218A00199200218A00089A0010960000CE0000A200009E0008960000CA0000000000
+BA0000B60000AE0000CE0000C20000CE0000B60000BA0000000000C20000000000E3000000000000
+0000000000000019BA4A19BA4A19BA4A00E30000E300318E9C318E9C318E9C000000000000000000
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E6000000FFFFFF0000005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E6089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241
+42848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000000000000000FFFFFFFFFFFFFFFFFF000000
+000000000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000000000000000000000FFFFFF000000FF
+FFFFFFFFFFFFFFFF000000FFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFFFFFF
+FF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000FFFFFFFFFFFF000000
+000000000000000000FFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFF00000000000000
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFF
+D6D2CEFFFFFFD6D2CED6D2CE0896005265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000FF
+FF00FFFF00FFFF00FFFF00FFFF00FFFF000000005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000005265E65265E6
+0000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000
+0000000000000000000000000000318E9C318E9C318E9C318E9C00E70000000000E30000DF0000DF
+0000000000DF0000E30000DF0000C200009E0000B600089A00009E00009E0000B20000AE00109600
+2986004A79085271087365196B6919736519218A00198E00009E00218A00089A0029860031820031
+82004279084279004A75083A7D004A7508318200298A00009E00089A0000B20000B200089A0000DB
+0000DB0000C20000C60000000000C60000C20000C60010920000AA0000AA0000D700000000000000
+00DF0000DF0000DF0000000000E30000000000000000E30000E300318E9C318E9C00000000000000
+00005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E6000000FFFFFFFFFFFF0000005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E6089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CE
+D6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6
+D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896005265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000FFFF00FFFF
+000000000000005265E6000000000000FFFF00FFFF000000000000005265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E6000000000000FFFF00FFFF0000000000
+00005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E6000000000000000000000000000000318E9C000000000000000000
+00000000000000E30000E30000DF0000000000DF0000CA0000DB0000CA0000C20000D70008960000
+9E0000B200218A00109200218A004279085A711052711052750831820000B200198E001096001092
+003A7D001992003A82004279007365195A71105A71105A71106B69104279004A750829860000AA00
+00A60000D20000CE0000DB00009E0000C60000000000000000BA0000A600009E0000DB0000DB0000
+D20000000000CA0000E70000DB0000DF0000000000000000E70000E300000000000000318E9C318E
+9C0000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000FFFFFF
+FFFFFFFFFFFF0000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E6089600089600D6D2CED6D2CE84828442
+4142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000
+000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E60000000000005265E65265E65265E65265E65265E60000000000005265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E60000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000E30000E70000
+000019BA4A00E30000000000E30019BA4A00000000E70000E30000000000000000000000D70000BE
+0000CA0000CA0000AA0000CE00009E00089600109600089600218A00198E002986003A7D00089600
+009E00089600009E00009E00198E003182003182006B69106B691073651973651973651973651963
+6D104A7908298600009E00009E0000CE0000C20000AA0008960000D20000000000C20000D70000BA
+0000E70000E30000000000000000BA0000CA0000E70000E70000DF0000000000E70000E300318E9C
+318E9C0000000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E6000000FFFFFFFFFFFFFFFFFFFFFFFF0000005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60896000896
+00D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6
+D2CED6D2CE0896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E6000000000000318E9C00000000000000E30000E30000E300000000000000000000000000
+00DF0000E30000000000000000000000000000000000000000DF0000D20000A60010960000A20000
+C600009E0000A60000A20000D20000DB00089600089A003182004A75085271087369196369107369
+196B69196369107365195A6D103A7D00218A0000A20000A20000A20000B60000B20000BE0000A200
+00000000BE0000CA0000E70000E70000000000E30000BE0000BA0000CA0000E70000DF0000DF0000
+000000E30000E300318E9C318E9C318E9C0000005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E6000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E6089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84
+8284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2
+CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E6000000318E9C000000000000318E9C00E30019
+BA4A00000000E70000000000000000DF0000E30000DF0000E30000E70000CA0000BA000000001096
+0000A60000D70000BE0000B20000C600009E0000CE0000D70000A20000A2003182007365197B6919
+6B69197B71217B69217B6D217B6D217B69196B69196369104A7508109600009E0000D70000B60000
+C60000BA0000DB0000B20000C20000000000000000B60000000000E30000E30000E30000BA0000CA
+0000E70000DF0000DF0000000019BA4A318E9C318E9C318E9C0000005265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E6000000FFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFF0000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E6089600089600D6D2CED6D2CE848284424142D6D2CEFFFF
+FFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896005265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000318E
+9C000000318E9C318E9C00E30000000000000000DF0000000000E30000E30000E70000DF0000DB00
+00000000000000E30000E70000AA0000BE0008960000C60000C60000B60000C60000A20010960000
+BE00089A005A71107B79217B71217B71217B79217B79217B75217B69217B69196B6919218A001992
+0000B20000B60000DB0000D20000A20000D20000B60000BE0000000000E30000000000C20000BA00
+00DF0000E70000CE0000E70000E70000DF00000000000000318E9C318E9C318E9C0000005265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000
+00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000005265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600D6D2CED6D2CE
+848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896
+005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E6000000000000318E9C000000318E9C00000000E30000E70000E70000DF0000000000
+000000000000000000000000000000BE0000E70000D70000D70000DB0010960000AA0000DB00089A
+0000A20000B200109200089A00198E006B69197B75217B7D217B79215A71107B75217B71217B6D21
+7B69215A6D10298600218A0000C20000AE0000B20000C20000CA0000CA0000D70000C20000000000
+CA0000000000BE0000C20000CA0000E30000DB0000DF0000E30000DF0000DF0000000000E300318E
+9C318E9C0000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E6000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000052
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E6089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241428482
+84424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CE
+FFFFFFD6D2CED6D2CE0896005265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E6000000318E9C000000318E9C00E70000E7
+0000E30000E30000000000000000E30000E30000DF0000000000D20000B20000B2003182003A7D00
+5A6D107365195275085271083A7D003A7D00109600218A005A71106B69107B75217B7D217B7D217B
+7D217B79217B75217B712173651963691029860000BA0000CE0008960000B200089A0000D20000DB
+0000BE0000CA0000000000E70000000000CA0000CE0000CE0000DF0000E30000E30000DF0000DF00
+00DF000000000000000000000000000000005265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E6000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFF0000005265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E6089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE
+D6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFF
+FFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896005265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000
+00000000000000000000000000000000E70000E70000000000E30000E30000E30000000010920021
+8A002986004279005A71107B6D217B6D217B7D217B7D217B6D217B69217365196B69107B65197B71
+217B79217B7D217B79217B75217B75217B6D217365196B6919636910318200109200089A0000CA00
+00D70000BA0000D70000D70000AE0000B60000000000E70000DF0000000000E30000DF0000DF0000
+DF0000E70000E30000000000000000E3000000000000000000005265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E6089600D6D2CED6D2CE848284424142D6
+D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E6000000000000318E9C00E30000000019BA4A00E30000000000E70000DF
+0000000000D200089600009E002986004279085A71105271107365197B79217B7521736519736519
+6369104A79086B69196369107B71217365196B69197B79217B79217B75217B6D216B69104A750831
+820010960000B20000AA0000DB0000CA0000D70000A60000E70000BE0000000000E70000E3000000
+0000000000DF0000E30000E70000E70000000000000019BA4A19BA4A00E300318E9C0000005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E6000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF0000005265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600D6D2
+CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142848284424142FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6
+D2CE0896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000318E9C000000000000
+00000000000000E70000E30000E30000000000CE0000B200109200218A00218E003A7D006B691952
+71107365194A75083A7D003182003A7D00427D005A71105A71105A6D107B69217B75217B79217B7D
+217B7D217B6519636910318200198E0000BE0010960000BA00089A0010920000AA0000BE0000E300
+00CA0000000000DF0000E30000000000000000000000E70000000019BA4A19BA4A00E300318E9C31
+8E9C0000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E6000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF0000005265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E6089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84828442
+4142848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFF
+FFD6D2CEFFFFFFD6D2CED6D2CE0896005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600
+0000000000318E9C318E9C00E30000E30000E30000E30019BA4A00E30000000000000000B2000896
+0000CA0000AE0000B200089600199200009E00009E00089A00318200298A00199200218A004A7508
+6369106B69195A71107B7D217B75217B6D214A7508198E0010920000AE00009E0000BE0000C60000
+AA0000D20000BE0000CA0000CA0000000000000000000000000000000000000000000000000000E3
+0000E30000E30000E300318E9C0000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E6000000FFFFFF0000005265E65265E600
+0000FFFFFFFFFFFF0000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E6089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2
+CED6D2CED6D2CE848284424142848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CEFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E6000000318E9C318E9C318E9C318E9C318E9C00E30000E300
+19BA4A00E30000000000000000C200198E0000CE0000B60010960000DF00009E0000B20000A60000
+A600009E00089A004A79084A75085A71107365197369195A6D10527108427908218A0000A20000AA
+0000B60000B60008960000AA00000000000000000000000000000000000000000000000000000000
+00000000000000000019BA4A00E30000E300318E9C318E9C0000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000
+005265E65265E65265E6000000FFFFFFFFFFFF0000005265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600D6D2CED6D2CE848284
+424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896005265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000318E9C318E9C00
+0000000000000000000000318E9C318E9C318E9C00E30000000000000000000000000000000000CA
+0000B60000DB0000B60000B600009E00009E00089A00218A003A7D002986004A75083A7D00298600
+218A00009E0000CE0000BA0000C60000C60000000000000000E70000BE0000CA0000E70000E30000
+0000000000FFFF00FFFF0000000000000000E30000E30000E300318E9C0000000000005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E60000005265E65265E65265E65265E65265E6000000FFFFFFFFFFFF0000005265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E6D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFF
+D6D2CED6D2CE0896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E60000000000000000000000005265E6000000000000000000000000000000000000000000
+19BA4A00E30000000000000000000000000000BE0000B60000C20000AA0000C60000AE00089A0010
+9200089A00109200089A0000CA00089A0000D20000D70010920000000000A60000C20000C60000CA
+0000CE0000DF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000318E9C000000000000
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000FFFF
+FFFFFFFF0000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E6D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE
+848284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6
+D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896005265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E600000000000000000000E30000DF0000DF0000000000000000BA0000CE
+0000B20000DB0000000000000000B20000A20000C60000A20000BE0000A20000C60000AE00000000
+00C60000C20000E70000DF0000E30000DF00000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000
+00000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E6000000FFFFFFFFFFFF0000005265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E6D6D2CED6D2CE848284424142D6D2CEFF
+FFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE5265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600000000000000E300
+00DF0000DF00000000000000000000000000FFFF00FFFF00000000000000089A0000BE0000D20000
+B20000C20000000000BA0000DF0000DF0000E30000DF0000DF00000000FFFF00FFFF00FFFF00FFFF
+00FFFF00FFFF00FFFF00FFFF000000005265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E6000000FFFFFFFFFFFF0000005265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6D6D2CED6D2
+CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFFFFFFFF
+FFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE52
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E600000000000000000000E300000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF
+0000000000E70000DF0000BA0000DF0000000000DF0000E30000E30000E30000E30000E300000000
+FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600
+089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6
+D2CEFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2
+CEFFFFFFD6D2CED6D2CE5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600
+00000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000000000FFFF00FFFF00
+FFFF00FFFF00FFFF00FFFF0000000000DF0000CE0000000000000000DF0000E30000E30000DF0000
+E70019BA4A00E30000E700000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF000000005265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E608960008960008960008960008960008960008
+9600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2
+CED6D2CE848284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE5265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E60000000000000000005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E600
+0000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF0000000000000000E30000E70000E3
+0000E70000E30019BA4A000000000000000000000000000000FFFF00FFFF00FFFF00FFFF00FFFF00
+FFFF000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E60896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142
+D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFF000000FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE5265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E60000000000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00000000
+0000000000000000000000000000000000000000005265E65265E65265E65265E65265E600000000
+0000FFFF00FFFF000000000000005265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600089600089600089600D6
+D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFFFFF
+FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000000000000000000000FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CE
+D6D2CE5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E60000000000005265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E6000000FFFF00FFFF00FFFF00FFFF00FF
+FF00FFFF000000005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E60000000000005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E6089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284
+424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFF
+FFFFD6D2CEFFFFFFD6D2CED6D2CE5265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000FFFF
+00FFFF00FFFF00FFFF00FFFF00FFFF000000005265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E6089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6
+D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE5265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E6000000000000FFFF00FFFF000000000000005265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE8482
+84424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFF
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE5265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E60000000000005265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFF
+FFD6D2CED6D2CE0896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E60000005265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E608960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2
+CE848284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+D6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+000896005265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E60000000000005265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CE
+FFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+000896000896000896000896000896000896000896000896000896000896000896005265E65265E6
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265
+E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E6000000
+5265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E65265E652
+65E65265E65265E65265E65265E65265E65265E65265E60896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600089600089600D6D2CED6
+D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142
+D6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6
+D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6
+D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000
+00000000000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFF
+FFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000
+0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE8482844241
+42D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFF000000000000FFFFFFFFFFFF
+000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF00
+0000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFF00
+0000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFF0000
+00000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2
+CED6D2CE089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482
+84424142D6D2CEFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000
+000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FF
+FFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFF
+FF000000000000FFFFFF000000000000000000000000000000000000000000000000000000FFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CE
+FFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFF
+D6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFF000000000000FFFFFFFFFFFF000000000000FF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFF000000000000000000FFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFF
+FFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+000000000000FFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FF
+FFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE84
+8284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFF000000000000FFFF
+FFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFF
+FFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFF000000000000FFFF
+FFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CE
+FFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFF
+FFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF0000
+00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000FFFFFFFFFFFFFFFFFF
+FFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFF
+FFFFD6D2CED6D2CE0896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6
+D2CE848284424142D6D2CEFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000
+000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000
+0000000000FFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF0000
+00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2
+CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFF000000000000FFFFFFFFFFFF000000
+000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF00000000
+0000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFF000000000000FFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000
+000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600D6D2CE
+D6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFF00
+0000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF0000
+00000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000FFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFF00000000
+0000FFFFFFFFFFFF000000000000FFFFFFFFFFFF000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2
+CE089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482844241
+42D6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFF
+D6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CE
+D6D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE84828442
+4142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CEFFFFFFD6
+D2CED6D2CE0896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CE84
+8284424142D6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2
+CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600089600089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFF
+FFD6D2CED6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CEFFFFFFD6D2CED6D2CE08960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600D6D2CED6D2CE
+848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CEFFFFFFD6D2CED6D2CE0896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+9600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+FFFFFFD6D2CED6D2CE08960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600089600089600089600089600089600089600089600089600
+08960008960008960008960008960008960008960008960008960008960008960008960008960008
+96000896000896000896000896000896000896000896000896000896000896000896000896000896
+00089600089600089600089600089600D6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6
+D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+848284848284FFFFFFD6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284D6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2
+CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CE848284
+424142D6D2CEFFFFFFD6D2CED6D2CE848284D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFF
+FFFFD6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284D6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284
+D6D2CED6D2CE000000D6D2CED6D2CE000000000000000000000000000000D6D2CED6D2CED6D2CE00
+0000000000D6D2CED6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CE0000000000000000
+00D6D2CED6D2CED6D2CE000000000000000000D6D2CED6D2CE000000000000000000000000000000
+D6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000000000D6D2CED6D2CED6D2CE00
+0000000000D6D2CED6D2CED6D2CE000000000000000000D6D2CED6D2CE0000000000000000000000
+00000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000000000
+000000D6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CE000000000000000000D6D2CED6
+D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE0000
+00000000000000000000000000D6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE000000000000D6D2CED6D2CE000000000000000000000000000000D6
+D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142D6D2CEFF
+FFFFD6D2CED6D2CE848284D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE
+000000D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000D6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE
+000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2
+CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000
+000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE00
+0000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000000000D6D2CED6D2CED6D2CE000000D6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFF848284D6D2CED6D2CED6D2
+CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284D6D2CE000000D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6
+D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2
+CE000000D6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000
+D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6
+D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CE
+000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6
+D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6
+D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFF848284
+848284D6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284D6D2CE000000D6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000000000000000000000D6D2
+CED6D2CED6D2CE000000000000000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE
+D6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000000000000000000000D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE000000000000000000000000D6D2CED6D2CE000000000000000000000000D6D2
+CED6D2CED6D2CE000000000000000000D6D2CED6D2CE000000000000000000000000D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE00
+0000D6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000000000000000D6D2CED6D2CE000000D6D2
+CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE
+000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE00
+0000000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2
+CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CEFFFFFF848284848284D6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2
+CE848284D6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000
+D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CE00000000
+0000000000000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CE000000
+D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6
+D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE
+000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000000000000000000000000000D6
+D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2
+CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE
+D6D2CED6D2CE000000000000000000000000000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CEFFFFFF848284848284D6D2CEFFFFFFD6D2CED6D2CED6D2CE848284424142
+D6D2CEFFFFFFD6D2CED6D2CE848284D6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6
+D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE00
+0000D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2
+CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CE
+D6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6
+D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2
+CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFF848284848284D6D2CEFFFFFF848284D6D2CED6
+D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284D6D2CE000000D6D2CED6D2CED6D2
+CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000
+D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6
+D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2
+CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000
+D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2
+CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CE000000D6D2CED6D2CED6D2CE
+000000D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6
+D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2
+CED6D2CE000000D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000
+D6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFF848284848284D6D2CEFFFF
+FF848284848284D6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284D6D2CE
+D6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CE00000000000000
+0000D6D2CED6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CE000000000000D6D2CED6D2
+CED6D2CE000000000000000000000000000000D6D2CED6D2CE000000000000000000D6D2CED6D2CE
+D6D2CE000000D6D2CED6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CE00000000000000
+0000D6D2CED6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CE000000000000000000D6D2
+CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE
+D6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CE000000000000000000D6D2CED6D2CED6
+D2CE000000000000000000D6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE0000
+00D6D2CED6D2CED6D2CED6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CE000000D6D2CE
+D6D2CED6D2CE000000000000000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFF848284
+848284D6D2CEFFFFFF848284848284D6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6
+D2CED6D2CE848284D6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CEFFFFFF848284848284D6D2CEFFFFFF848284848284D6D2CEFFFFFFD6D2CED6D2CED6D2CE8482
+84424142D6D2CEFFFFFFD6D2CED6D2CE848284D6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE000000D6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE00
+0000D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CEFFFFFF848284848284D6D2CEFFFFFF848284848284D6D2CEFFFFFF848284
+D6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE848284D6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFF848284848284D6D2CEFFFFFF848284848284D6
+D2CEFFFFFF848284848284D6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CE8482
+84D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CEFFFFFF848284848284D6D2CEFFFF
+FF848284848284D6D2CEFFFFFF848284848284D6D2CED6D2CED6D2CED6D2CE848284424142D6D2CE
+FFFFFFD6D2CED6D2CEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CEFFFFFFD6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6
+D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2
+CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE
+D6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CED6D2CE848284424142D6D2CE84828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482848482
+84848284848284848284848284848284848284848284848284848284848284848284848284848284
+84828484828484828484828484828484828484828484828484828484828484828484828484828484
+82848482848482848482848482848482848482848482848482848482848482848482848482844241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+42414242414242414242414242414242414242414242414242414242414242414242414242414242
+41424241424241424241424241424241424241424241424241424241424241424241424241424241
+42424142424142424142424142424142424142424142424142424142424142424142424142424142
+424142424142424142424142
+%%EndData
+[106 0 0 -23 397 89] rect
+gsave
+1 0 0 rgb
+F
+grestore
+0 0 0 rgb
+1 w
+0 j
+0 J
+[] 0 d
+S
+/Helvetica-Bold 14 sf
+(Map Window)
+406 72 1 1 1 rgb
+T
+[67 0 0 -23 155.348 180.826] rect
+gsave
+1 0 0 rgb
+F
+grestore
+0 0 0 rgb
+1 w
+0 j
+0 J
+[] 0 d
+S
+/Helvetica-Bold 14 sf
+(Legend)
+164.348 163.826 1 1 1 rgb
+T
+[77 0 0 -23 315.391 319.522] rect
+gsave
+1 0 0 rgb
+F
+grestore
+0 0 0 rgb
+1 w
+0 j
+0 J
+[] 0 d
+S
+/Helvetica-Bold 14 sf
+(Tool Bar)
+324.391 302.522 1 1 1 rgb
+T
+[87 0 0 -23 203.739 60.7391] rect
+gsave
+1 0 0 rgb
+F
+grestore
+0 0 0 rgb
+1 w
+0 j
+0 J
+[] 0 d
+S
+/Helvetica-Bold 14 sf
+(Status Bar)
+212.739 43.7391 1 1 1 rgb
+T
+%%PageTrailer
+showpage
+%%Trailer
+end
+%%DocumentSuppliedResources: procset Linux-Sketch-Procset 1.0 2
+%%EOF

Added: packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.sk
===================================================================
--- packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.sk	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/manual/images/1_2_mainwindow.sk	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,52 @@
+##Sketch 1 2
+document()
+layout((540,400),0)
+layer('Layer 1',1,1,0,0,(0,0,0))
+bm(140059220,'../../../../../../.gnome-desktop/Screenshot-2.png')
+im((19.6378,35.9449),140059220)
+G()
+fp((1,0,0))
+lw(1)
+r(106,0,0,-23,397,89)
+fp((1,1,1))
+le()
+lw(1)
+Fn('Helvetica-Bold')
+Fs(14)
+txt('Map Window',(406,72))
+G_()
+G()
+fp((1,0,0))
+lw(1)
+r(67,0,0,-23,155.348,180.826)
+fp((1,1,1))
+le()
+lw(1)
+Fn('Helvetica-Bold')
+Fs(14)
+txt('Legend',(164.348,163.826))
+G_()
+G()
+fp((1,0,0))
+lw(1)
+r(77,0,0,-23,315.391,319.522)
+fp((1,1,1))
+le()
+lw(1)
+Fn('Helvetica-Bold')
+Fs(14)
+txt('Tool Bar',(324.391,302.522))
+G_()
+G()
+fp((1,0,0))
+lw(1)
+r(87,0,0,-23,203.739,60.7391)
+fp((1,1,1))
+le()
+lw(1)
+Fn('Helvetica-Bold')
+Fs(14)
+txt('Status Bar',(212.739,43.7391))
+G_()
+guidelayer('Guide Lines',1,0,0,1,(0,0,1))
+grid((0,0,20,20),0,(0,0,1),'Grid')

Added: packages/thuban/branches/upstream/current/Doc/manual/images/2_4_session_tree.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/2_4_session_tree.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_fullextent.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_fullextent.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_fulllayerextent.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_fulllayerextent.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_fullshapeextent.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_fullshapeextent.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_pan.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_pan.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_zoomin.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_zoomin.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_zoomout.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_2_zoomout.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_3_identify.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_3_identify.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_3_label.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_3_label.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_invisible.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_invisible.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_legend.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_legend.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_movedown.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_movedown.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_moveup.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_moveup.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_popup_menu.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_popup_menu.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_props.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_props.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_tobottom.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_tobottom.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_totop.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_totop.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_visible.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_5_visible.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/3_rename_map.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/3_rename_map.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/4_2_layer_properties.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/4_2_layer_properties.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/4_2_raster_layer_properties.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/4_2_raster_layer_properties.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/5_2_custom_ramp.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/5_2_custom_ramp.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/5_2_quantiles.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/5_2_quantiles.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/5_2_uniform_dist.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/5_2_uniform_dist.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/5_2_unique_values.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/5_2_unique_values.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/5_3_genclass.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/5_3_genclass.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/5_classification.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/5_classification.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/6_projection.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/6_projection.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/7_1_table_view.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/7_1_table_view.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/7_2_5_join.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/7_2_5_join.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/8_int_error.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/8_int_error.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/app_postgis_add_layer.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/app_postgis_add_layer.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/app_postgis_db_add.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/app_postgis_db_add.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/images/app_postgis_db_management.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/images/app_postgis_db_management.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/mainwindow.png
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/mainwindow.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/mainwindow.xcf
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Doc/manual/mainwindow.xcf
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Doc/manual/thuban-manual-de.xml
===================================================================
--- packages/thuban/branches/upstream/current/Doc/manual/thuban-manual-de.xml	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/manual/thuban-manual-de.xml	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,2400 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book
+	PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+    [<!ENTITY imgscale "60">]>
+<!-- $Revision: 2627 $ -->
+<book>
+  <bookinfo>
+    <title>Benutzerhandbuch für Thuban 1.0</title>
+	<authorgroup>
+      <author>
+        <firstname>Jonathan</firstname><surname>Coles</surname>
+      </author>
+      <author>
+        <firstname>Jan-Oliver</firstname><surname>Wagner</surname>
+      </author>
+      <author>
+        <firstname>Frank</firstname><surname>Koormann</surname>
+      </author>
+	</authorgroup>
+    <copyright>
+      <year>2004</year>
+      <holder>Intevation GmbH</holder>
+    </copyright>
+   <revhistory>
+<!-- comment this first revision out when releasing a real version -->
+     <revision>
+        <revnumber>CVS version $Id: thuban-manual-de.xml 2627 2005-06-27 15:52:08Z jan $</revnumber>
+        <date></date>
+        <revremark>Under development.</revremark>
+     </revision>
+<!--
+     <revision>
+        <revnumber>1.0.0</revnumber>
+        <date>nn-Mmm-2004</date>
+        <revremark>
+			Corresponds to Thuban 1.0.0.
+		</revremark>
+     </revision>
+-->
+  </revhistory>
+
+  </bookinfo>
+
+  <chapter><title>Einführung</title>
+	<para>
+	Thuban ist ein interaktiver Geodaten-Betrachter.
+	Die Entwicklung wurde seinerzeit gestartet, da es zu dieser Zeit
+	keinen einfachen interkativen Betrachter für Geo-Daten als Freie
+	Software gab.
+	Thuban ist im wesentlichen in der Programmiersprache Python implementiert und
+	nutzt die wxWidgets (ehemals: wxWindows) Bibliothek die es erlaubt
+	Thuban auf verschiedenen Plattformen laufen zu lassen, darunter GNU/Linux
+	und Windows.
+	</para>
+	<para>
+	Geodatenbetrachter sind wichtige Werkzeuge die es gestatten, einen visuelle
+	Eindruck des räumlichen (gegenseiten) Bezuges von Informationen zu bekommen
+	die ansonsten anhand der reinen Daten nicht leicht ersichtlich sind.
+	Thuban erlaubt dem Benutzer, Sitzungen zu erzeugen, die geografische
+	Daten darstellen. Diese können dann erforscht werden indem er durch sie
+	sie navigieren und die Art der Darstellung ändern kann.
+	Die Ergebnisse können gespeichert oder gedruckt werden.
+	</para>
+	<para>
+	Thuban strukturiert eine Sitzung hierarchisch.
+	Eine Sitzung besteht aus Ebenen. Jede Ebene rerpäsentiert
+	einen bestimmten Datensatz.
+	Beispielsweise eine Ebene für Strassen und eine weitere für Gebäude.
+	Die Ebenen können sowohl Vektor-Daten beschreiben als auch Raster-Daten.
+	</para>
+
+	<section><title>Installation</title>
+        <para>
+        Thuban is actively supported under Debian Testing (sarge), RedHat 7.2, 
+        and Windows 2000. Thuban depends on the following packages. These
+        packages can also be found on the 
+        <ulink url="http://thuban.intevation.org/download.html">
+        Thuban Download site
+        </ulink>.
+	</para>
+	<para>
+	Required:
+        <itemizedlist>
+            <listitem><para>Python 2.2.1 
+			(<literal>http://www.python.org</literal>)
+			</para></listitem>
+            <listitem><para>wxWindows 2.4 
+			(<literal>http://www.wxwindows.org</literal>)
+			</para></listitem>
+            <listitem><para>wxPython 2.4 
+			(<literal>http://www.wxpython.org</literal>)
+			</para></listitem>
+            <listitem><para>proj 4.4.5 Projection Library 
+			(<literal>http://www.remotesensing.org/proj/</literal>)
+			</para></listitem>
+            <listitem><para>SQLite 2.8.3 
+			<literal>http://www.hwaci.com/sw/sqlite/</literal>)
+			</para></listitem>
+            <listitem><para>PySQLite 0.4.3 
+			(<literal>http://pysqlite.sourceforge.net</literal>)
+			</para></listitem>
+	</itemizedlist>
+	</para>
+	<para>
+	Optional:
+        <itemizedlist>
+            <listitem><para>GDAL 1.1.8 
+			(<literal>http://www.remotesensing.org/gdal/</literal>)
+			</para></listitem>
+            <listitem><para>psycopg 1.0.8 
+			(<literal>http://initd.org/software/psycopg</literal>)
+			</para></listitem>
+	    </itemizedlist>
+        </para>
+		<para>
+		Along with the source codes, the download page also offers full
+		installation packages for Debian, Windows and RPM-based systems
+		(Mandrake, RedHat, SuSE, etc).
+		</para>
+  		<section><title>RPM-based GNU/Linux Systems</title>
+  			<section><title>Installing Binary Packages</title>
+				<para>
+				The most wide-spread RPM-based GNU/Linux
+				Systems are RedHat, Mandrake and SuSE. 
+				The documentation of these distributions
+				should contain information about how to 
+				install third-party RPM packages.
+				Nonetheless, a short summary is provided here.
+				</para>
+				<para>
+				RPM packages can be installed applying several 
+				tools. The most basic one is the command line 
+				program "rpm".  The hardware architecture is 
+				identified in the name of RPM packages, eg. 
+				'i386' for most Intel/AMD architectures.  
+				If you have a different hardware architecture, 
+				where no binary RPM packages are provided, 
+				you must rebuild binary packages from the 
+				RPM source packages first (see below).
+				Typical rpm commands look like:
+
+				<programlisting>
+				rpm --install Thuban-0.9.0-1.i386.rpm
+				</programlisting>
+
+				Depending on what you already have installed 
+				on your system, you are informed that some 
+				packages are required, but not installed. 
+				You need to install them first. Either they 
+				are provided by your GNU/Linux distributor 
+				or available somewhere on the Internet.  
+				The more essential and special ones are 
+				provided together with the Thuban package.
+				</para>
+
+				<para>
+				For rpm exist some graphical user interfaces, notably
+				kpackage, GnoRPM and xrpm.
+				</para>
+
+				<para>
+				Make yourself familiar with one of the tools and apply it
+				to install the packages.
+				Note, that you need to be administrator (root) for the system
+				to do that.
+				</para>
+  			</section>
+  			<section><title>Build Binaries from Source Packages</title>
+				<para>
+				This section describes howto build RPM install-packages
+				from RPM source-packages.
+				This adapts and optimizes an install-package specifically
+				to your system.
+				This is especially helpful to resolve version conflicts of
+				dependent packages. Furthermore, install-packages for other
+				platforms (e.g. PowerPC) can be created.
+				</para>
+
+				<para>
+				Note: rpm must be at least version 4. Execute
+				<literal>rpm --version</literal> to find out about the version.
+				</para>
+
+				<para>
+				You need to do the following preparations to be able to
+				build the packages as a regular user. You should now
+				perform the package buling as root since this
+				might cause damage to your system.
+        		<itemizedlist>
+            		<listitem>
+						<para>
+						Create RPM directory structure:
+						Choose a directory (e.g. $HOME/myrpm) and create the
+						subdirectories BUILD, RPM, SOURCES, SPECS and SRPMS.
+						A possible command sequence for this is:
+						<programlisting>
+						mkdir $HOME/freegisrpm
+						cd $HOME/freegisrpm
+						mkdir BUILD RPMS SOURCES SPECS SRPMS
+						</programlisting>
+						</para>
+					</listitem>
+					<listitem>
+						<para>
+						Set environment variable RPM_DIR:
+						<programlisting>
+						export RPM_DIR=$HOME/freegisrpm
+						</programlisting>
+						</para>
+					</listitem>
+					<listitem>
+						<para>
+						Create $HOME/.rpmmacros:
+						This file sets general preferences and some
+						specific settings for signing packages.
+						If you don't have a GnuPG-key, you can skip
+						the signature settings i.e. drop the last 4 lines.
+						A signature becomes important when you want to
+						give away packages to third parties.
+						<programlisting>
+<![CDATA[
+%packager Name Lastname <Name.Lastname at mydomain.example> 
+
+%_topdir /home/mylogin/myrpm
+
+%_signature gpg
+%_gpg_name Name Lastname
+%_pgp_path ~/.gnupg
+%_pgpbin /usr/bin/gpg
+]]>
+						</programlisting>
+						</para>
+					</listitem>
+        		</itemizedlist>
+
+				Now you can install any RPM source-package.
+				It's components are installed into the corresponding
+				subdirectories of your rpm-directory.
+				Essentially these are the sources (into directory SOURCES)
+				and the so-called spec-file which contains all build
+				instructions. The spec-file will go into the SPEC directory.
+				Example:
+				<literal>rpm --install Thuban-0.9.0-1.src.rpm</literal>
+				</para>
+
+				<para>
+				Create install-package:
+				Go to the directory with the spec-files and rebuild the
+				package:
+				<programlisting>
+cd $HOME/mypm/SPECS
+rpm -bb thuban.spec
+				</programlisting>
+				Next, you will find the newly created package in
+				$HOME/myrpm/RPMS/i386.
+				If you build the package for another architecture than
+				i386, then the name of the directory has a corresponding name.
+				</para>
+				<para>
+				For documentation of RPM, either type
+				<literal>man rpm</literal> or <literal>rpm --help</literal>.
+				This will provide you with information on the various command
+				line options of RPM.
+				For more information see the
+        		<ulink url="http://www.rpm.org/">homepage of RPM</ulink>.
+				</para>
+  			</section>
+  		</section> <!-- Intro - Installation - RPM-->
+
+		<section><title>Win32 Systems</title>
+		<para>
+			A common installation package of Thuban for Win32
+			systems is available from the Thuban website download
+			section. This installation package is configured for
+			displaying file based vector data (Shapefiles). For the
+			display of raster data or the connection to spatial
+			databases additional steps are needed.  
+		</para>
+		<para>
+			The required Python packages are listed and linked on
+			the download page as well.  If you don't have Python
+			installed already, download the packages for Python,
+			wxPython for Python and the SQLite Python Libraries as
+			well as the Thuban package. Install all four packages
+			in the order: Python, wxPython, SQLite, Thuban. Follow
+			the installation instructions provided by the seperate
+			setups. The Thuban installation package will add an
+			entry in the menu folder you configured.
+		</para>
+		<section><title>Raster Data: Installation of GDAL</title>
+		<para>
+			Enabling the raster data features of Thuban is 
+			straight forward. For the examples we assume that 
+			Thuban has been installed under 
+			<literal>C:\Thuban</literal>:
+			<itemizedlist>
+			<listitem>
+			<para>
+			Download the zip-archive <ulink 
+			url="ftp://intevation.de/thuban/win2k/gdal-win2k.zip"
+			>gdal-win2k</ulink>. 
+			</para></listitem>
+			<listitem><para>Extract the archive (e.g. with 
+			<ulink 
+			url="http://www.info-zip.org/pub/infozip/WiZ.html"
+			>WiZ (InfoZip)</ulink>) into the 
+			<literal>C:\Thuban\Lib</literal>
+			directory of your Thuban installation.
+			</para>
+			</listitem>
+			<listitem>
+			<para>
+			Extent the <varname>PYTHONPATH</varname> 
+			environment variable (in your Windows Control Panel)
+			to make the new libraries available for Thuban.
+			<programlisting>
+%PYTHONPATH%;C:\Thuban\Lib\gdal;C:\Thuban\Lib\gdal\pymod
+			</programlisting>
+			</para>
+			</listitem>
+			<listitem>
+			<para>
+			Extent also the <varname>PATH</varname>
+			environment variable accordingly:
+			<programlisting>
+%PATH%;C:\Thuban\Lib\gdal
+			</programlisting>
+			</para>
+			</listitem>
+			</itemizedlist>
+			After this installation steps Thuban is ready to
+			display raster data (e.g. the
+			<literal>island.tif</literal> from the Iceland Demo
+			data set.
+		</para>
+		</section> <!-- Win32: GDAL-->
+
+		<section><title>Working with PostGIS: Installation of PsycoPG</title>
+		<para>
+			To access PostgreSQL/PostGIS spatial databases with
+			Thuban you have to install the PsycoPG package for 
+			Windows:
+			<itemizedlist>
+			<listitem>
+			<para> 
+			Download the zip-archive 
+			<ulink 
+				url="http://stickpeople.com/projects/python/win-psycopg/win-psycopg22.zip"
+			>win-psycopg22.zip</ulink>.
+			</para>
+			</listitem>
+			<listitem>
+			<para> 
+			Extract the zip-archive into a directory either already
+			in your <varname>PYTHONPATH</varname> or extent your 
+			<varname>PYTHONPATH</varname> variable to the directory 
+			you have extracted the archive to.
+			</para>
+			</listitem>
+			</itemizedlist>
+			For installation and maintenance of spatial databases
+			we refer to the  <ulink
+			url="http://postgis.refractions.net"
+			>PostGIS Homepage</ulink>.
+		</para>
+		</section> <!-- Win32: PsycoPG-->
+
+		</section> <!-- Intro - Installation - Win32 -->
+	</section>
+
+	<section><title>Internationalisierung</title>
+	  <para>
+	  Thuban ist mit Unterstützung für Internaionalisierung realisiert.
+	  Bisher wurde Thuban in folgende Sprachen (neben der Basis Englisch) übersetzt:
+	  <itemizedlist>
+		<listitem><para>Französisch</para></listitem>
+		<listitem><para>Deutsch</para></listitem>
+		<listitem><para>Italienisch</para></listitem>
+		<listitem><para>Portugiesisch (Brasilien)</para></listitem>
+		<listitem><para>Russisch</para></listitem>
+		<listitem><para>Spanisch</para></listitem>
+	  </itemizedlist>
+	  </para>
+
+	<para>
+	  Um die Internationalisierung auf POSIX Systemen (wie etwa GNU/Linux)
+	  zu verwenden, muss die Umgebungsvariable LC_ALL entsprechend
+	  gesetzt werden (z.B. LC_ALL=de_DE für Deutsch).
+	  Prüfen Sie die Dokumentation zu Ihrem System für Details
+	  und die unterstützten Einstellungen.
+	  Normalweise haben Sie Ihre Sprache bereits mit der Installation
+	  oder beim einloggen bereits vorausgewählt.
+	  Trotzdem kann auch dann noch durch Setzen von LC_ALL auf
+	  der Kommandozeile beim Aufruf von Thuban eine andere Sprache
+	  gesetzt werden:
+	</para>
+	<programlisting>
+	  LC_ALL=fr_FR thuban.py
+	</programlisting>
+
+	<para>
+	MS Windows Benutzer müssen die Sprache über die Kontroll-Leiste einstellen
+	welche grundsätzlich alle Anwendungen beeinflusst.
+	</para>
+	</section>
+
+	<section><title>Das Hauptfenster</title>
+	  <para>
+		<figure><title>Das Hauptfenster</title>
+		  <mediaobject>
+			<imageobject> <imagedata fileref="../images/1_2_mainwindow.png" format="PNG" scale="&imgscale;"/> </imageobject>
+			<imageobject> <imagedata fileref="./images/1_2_mainwindow.ps" format="EPS" scale="&imgscale;"/> </imageobject>
+		  </mediaobject>
+		</figure>
+	  </para>
+
+	  <para>
+	  Das Hauptfenster stellt die aktuelle Karte dar. Hier kann der
+	  Benutzer mit der Karte interagieren indem er die verschiednen
+	  Werkzeuge anwendet.
+	  </para>
+
+      <para>
+	  Die Legende auf der linken Seite zeigt eine Liste der aktuellen
+	  Ebenen und alle dargestellten Klassifikations-Gruppen.
+	  Bei diesem Beispiel haben alle Geo-Objekte Ebenen eine voreingestellte
+	  Klassifizierung wie die jeweiligen Geo-Objekte in den einzelnen
+	  Ebenen gezeichnet werden sollen.
+	  Die Ebenen die weiter oben in der Liste dargestellt werden über
+	  die darunter aufgelisteten gezeichnet.
+	  Die Legende kann durch Anwahl des X in der oberen rechten Ecke
+	  geschlossen werden.
+	  Um die Legenden-Ansicht wieder zu öffnen, wählen Sie
+	  <menuchoice>
+	  <guimenu>Karte</guimenu>
+	  <guimenuitem>Legende</guimenuitem>
+	  </menuchoice>.
+	  Das Legenden-Fenster ist lösbar. Das bedeutet, dass sie vom Hauptfenster
+	  abgelöst und dann als eigenständiges Fenster
+	  positioniert werden kann. Dies wird durch den kleinen Schalter
+	  neben dem X gemacht. Erneutes Anwählen des Schalters läßt das
+	  Legenden-Fenster wieder in das Hauptfenster integrieren.
+	  </para>
+	  <para>
+	  Die Status-Leiste zeigt verschiedene Informationen jeweils
+	  abhängig vom Kontext. Wählt der Benutzer einen Menüpunkt
+	  dann wird in der Status-Leiste ein Hilfetext zu dem jeweiligen
+	  Menüpunkt angezeigt.
+	  Ist eines der Werkzeuge aktiviert, so wird in der Status-Leiste
+	  die Position angegeben über der der Maus-Cursor auf der Karte
+	  steht.
+	  </para>
+	  <para>
+	  Die Werkzeugleiste erlaubt direkten Zugriff auf häufig
+	  benötigte Werkzeuge.
+	  Schwebt der Maus-Zeiger über einem Knopf wird eine Kurz-Info
+	  über das jeweilige Werkzeug gegeben.
+	  Folgende Werzeuge stehen zur Verfügung: Hineinzoomen,
+	  Herauszoomen, Verschieben, Zur vollen Kartenausdehnung zoomen,
+	  Zur vollen Ebenenausdehnung zoomen, Zur vollen Auswahlausdehnung zoomen,
+	  Identifizieren, Labels hinzufügen/entfernen.
+	  Alle Werkzeuge werden in diesem Handbuch noch detaillierter beschrieben.
+	  </para>
+	</section>
+
+  </chapter>
+
+  <chapter><title>Session Management</title>
+
+  	<section><title>Eine neue Session beginnen</title>
+		<para>
+		Eine neue Session wird gestartet über
+		<menuchoice>
+		<guimenu>Datei</guimenu>
+		<guimenuitem>Neue Session</guimenuitem>
+		</menuchoice>. 
+		Falls bereits eine Session geladen ist und seit der letzten
+		Speicherung verändert wurde, so wird nun nachgefragt, ob
+		diese Session zunächst gespeichert werden soll.
+		Eine neue Session besteht aus einer leeren Karte
+		ohne Ebenen, Tabellen und Projektion.
+		</para>
+	</section>
+
+	<section><title>Eine Session öffnen</title>
+		<para>
+		Eine Session kann geöffnet werden über
+		<menuchoice>
+		<guimenu>Datei</guimenu>
+		<guimenuitem>Öffne Session</guimenuitem>
+		</menuchoice>.
+		Es wird ein Dateiauswahl-Dialog geöffnet um eine
+		Thuban Session Datei auszuwählen. Diese Dateien enden
+		auf <varname>.thuban</varname>. Wird eine Datei ausgewählt und mit
+		<guibutton>OK</guibutton> bestätigt, so wird die entsprechende
+		Session in Thuban geladen.
+
+		Ist bereits eine Session geladen und seit dem letzten Speichern modifiziert
+		worden, so wird nachgefragt, ob zunächst die alte Session gespeichert werden
+		soll.
+		</para>
+	</section>
+
+	<section><title>Eine Session speichern</title>
+		<para>
+		Eine Session kann gepsiechert werden über
+		<menuchoice>
+		<guimenu>Datei</guimenu>
+		<guimenuitem>Session Speichern</guimenuitem>
+		</menuchoice>.
+		Handelt es sich bei der aktuellen Session nicht um eine
+		neue und ungespeicherte, so wird die entsprechende Datei
+		mit den Daten der aktuellen Session überschrieben.
+		Im Falle einer neuen und noch nicht gespeicherten Session
+		wird ein Dateiauswahl-Dialog geöffnet um einen Namen
+		für die zu speicherende Session auszuwählen.
+		Thuban Session Dateien sollten mit der Endung
+		<varname>.thuban</varname> versehen werden.
+		Existiert bereits eine Datei mit dem gleichen Namen
+		wird der Benutzer gefragt ob diese überschrieben
+		oder ein neuer Name gewählt werden soll.
+		</para>
+	</section>
+
+	<section><title>Der Session Info-Baum</title>
+		<para>
+		<figure>
+		<title>Session Info-Baum</title>
+		<mediaobject>
+		<imageobject><imagedata fileref="../images/2_4_session_tree.png" format="PNG" scale="&imgscale;"/></imageobject>
+		<imageobject><imagedata fileref="./images/2_4_session_tree.eps" format="EPS" scale="&imgscale;"/></imageobject>
+		</mediaobject>
+		</figure>
+		</para>
+		<para>
+		Der Session Info-Baum ist hauptsächlich für Software-Entwickler gedacht
+		die an Thuban arbeiten.
+		Er stellt eine Reihe von internen Daten zur Session, der Karte, den
+		Ebenen usw. dar. Er wird geöffnet über
+		<menuchoice>
+		<guimenu>Datei</guimenu>
+		<guimenuitem>Session Baum</guimenuitem>
+		</menuchoice>. 
+		</para>
+	</section>
+  </chapter>
+
+  <chapter><title>Karten Management</title>
+    <para>
+	Die Karte besteht aus eine Anzahl Ebenen wobei jede Ebene einen
+	Datensatz mit bestimtem Typ repräsentiert. Mit Interaktion auf der
+	Karte kann ein Benutzer die Daten visuell erforschen.
+    </para>
+    <para>
+	Die Karte kann einen Namen haben der dann in der Kopfzeile des
+	Thuban Fensters auftaucht. Der Kartenname kann geändert werden
+	über
+    <menuchoice>
+    <guimenu>Karte</guimenu>
+    <guimenuitem>Umbennen</guimenuitem>
+    </menuchoice>.
+    </para>
+    <para>
+    <inlinemediaobject>
+    <imageobject> 
+    <imagedata fileref="../images/3_rename_map.png" format="PNG" scale="&imgscale;"/> 
+    </imageobject> 
+    <imageobject> 
+    <imagedata fileref="./images/3_rename_map.eps" format="EPS" scale="&imgscale;"/> 
+    </imageobject>
+    <textobject> <phrase>Karte umbennen</phrase> </textobject>
+    </inlinemediaobject>
+    </para>
+
+	<section><title>Hinzufügen und Entfernen von Ebenen</title>
+	<para>
+	Es gibt drei Typen von Ebenen aus denen eine Karte besteht:
+	Shape Ebene, Datenbank Ebene und Bildebene.
+	Shape Ebenen sind im Shapefile Format gespeichert welches
+	weit verbreitet für die Speicherung von geografischen Objekten
+	genutzt wird.
+	Die Dateien haben die Endung ``.shp''. Mit der eigentlichen Shape
+	Datei ist eine Datenbank Datei welche die Attribut-Daten zu dem
+	Shapefile enthält. Diese Datenbank Datei verwendet das dBase Format
+	und hat die Endung ``.dbf''. Beide Dateien müssen den selben
+	Basisnamen haben. So gehören zum Beispiel die Dateien
+	strassen.shp und strassen.dbf zusammen.
+	</para>
+	<itemizedlist>
+	<listitem>
+	<para>
+		Shape Ebenen können zur Karte hinzugefügt werden mit
+        <menuchoice>
+        <guimenu>Karte</guimenu>
+        <guimenuitem>Ebene hinzufügen</guimenuitem>
+        </menuchoice>.
+		Zunächst werden im Dateiauswahl Dialog nur die ``.shp'' Dateien
+		angezeigt, was für die Auswahl vollkommen ausreicht.
+		Falls Sie aber auf Ansicht aller Dateien umschalten, und dann
+		einer der assoziierten Dateien (z.B. mit der Endung ``.dbf'')
+		auswählen, so verwendet Thuban den Basisnamen um die entsprechende
+		Shape Datei zu laden,
+		</para>
+		<para>
+		Der Dateidialog für Shape Dateien erlaubt es auch, viele
+		Dateien gleichzeitig auszuwählen. Verwenden Sie dafür
+		die Umschalt-Taste gleichzeitig mit der linken Maustaste um
+		die Auswahl zu erweitern.
+		</para>
+	</listitem>
+
+	<listitem>
+		<para>Datenbankebenen können zu Karte hinzugefügt werden mit
+	<menuchoice>
+        <guimenu>Karte</guimenu>
+        <guimenuitem>Datenbankebene hinzufügen</guimenuitem>
+        </menuchoice>.
+	Es wird ein Dialog mit zwei Listen geöffnet.
+	Die linke Liste zeigt alle derzeit offenen Datenbankverbindungen dieser
+	Session an. Eine Liste der verfügbaren Ebenen aus einer Datenbankverbindung
+	wird steht auf der rechten Seite. Aus dieser Liste können Sie eine
+	beliebige Ebene zum Öffnen auswählen. Der Dialog wird dabach
+	automatisch beendet.
+    	</para>
+	<para>
+	Siehe auch Anhang ``Mit PostGIS arbeiten'' für weitere Details.
+	</para>
+	</listitem>
+
+	<listitem>
+    	<para>
+        Bildebenen können zur Karte hinzugefügt werden mit
+        <menuchoice>
+        <guimenu>Karte</guimenu>
+        <guimenuitem>Bildebene hinzufügen</guimenuitem>
+        </menuchoice>.
+		Es ist wichtig, dass eine korrekte Bilddatei ausgewählt für
+		die auch geographische Daten (Projektions) vorliegen.
+		Diese Daten können in die Bilddatei eingebettet sein oder
+		als separate Datei vorliegen. Können diese Daten nicht
+		gefunden werden, so wird Thuban einen Fehler melden.
+    	</para>
+	</listitem>
+	</itemizedlist>
+  	</section>
+
+  	<section><title>Navigation</title>
+    	<para>
+		Die Karte kann erforscht werden indem die Navigationswerkzeuge
+		aus der Werkzeugleiste oder über das Menü
+        <menuchoice><guimenu>Karte</guimenu></menuchoice> ausgewählt werden.
+    	</para>
+	<itemizedlist>
+	<listitem>
+    	<para>
+        Das ZoomIn Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_zoomin.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_zoomin.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>ZoomIn Werkzeug</phrase> </textobject>
+        </inlinemediaobject>
+		vergrößert einen Bereich aus der Karte. Ein einmaliges Klicken auf
+		die Karte vergrößert die Karte um das Doppelte und zentriert auf den
+		angewählten Punkt. Klicken und Ziehen selektiert einen Bereich
+		der dann so vergrößert wird, dass er das Fenster ausfüllt.
+    	</para>
+	</listitem>
+	<listitem>
+    	<para>
+        Das ZoomOut Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_zoomout.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_zoomout.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>ZoomOut Werkzeug</phrase> </textobject>
+        </inlinemediaobject>
+		verkleinert die Karte, so dass ein größerer Bereich zu sehen ist.
+		Ein einzelnen Klick verkleinert die Karte um Faktor 2.
+		Klicken und Ziehen selektiert einen Bereich in den die gesamte sichtbare
+		Karte im Fenster hineinverkleinert wird.
+    	</para>
+	</listitem>
+	<listitem>
+    	<para>
+        Das Verschieben Werkzeug 
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_pan.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_pan.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Verschieben Werkzeug</phrase> </textobject>
+        </inlinemediaobject>
+        gestattet es dem Benutzer die Karte durch klicken und
+	ziehen mit gedrückter Maustaste zu verschieben.
+    	</para>
+	</listitem>
+	<listitem>
+    	<para>
+        Das Volle Ausdehnung Werkzeug 
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_fullextent.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_fullextent.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Volle Ausdehnung Werkzeug</phrase> </textobject>
+        </inlinemediaobject>
+        skaliert die Zoom-Stufe so, dass die gesamte sichtbare Karte im
+	Fenster dargestellt wird.
+    	</para>
+	</listitem>
+	<listitem>
+    	<para>
+        Das Voll Ebenen-Ausdehnung Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_fulllayerextent.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_fulllayerextent.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Volle Ebenen-Ausdehnung Werkzeug</phrase> </textobject>
+        </inlinemediaobject>
+        skaliert die Zoom-Stufe so, dass die akutelle Ebene vollständig
+	im Fenster dargestellt wird. Ist keine Ebene ausgewählt, so
+	ist dieser Knopf ausgegraut und damit nicht verfügbar.
+    	</para>
+	</listitem>
+	<listitem>
+    	<para>
+        Das Volle Shape-Ausdehnung Werkzeug 
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_fullshapeextent.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_fullshapeextent.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Volle Shape-Ausdehnung Werkzeug</phrase> </textobject>
+        </inlinemediaobject>
+        skaliert die Zoom-Stufe so, dass die aktuell ausgewählten Shapes
+	vollständig in das Fenster eingepasst sind.
+        Handelt es sich bei der Auswahl nur um einen einzelnen Punkt
+	so wird dieser zentriert dargestellt und bis zu einem gewissen
+	grad gezoomed.
+	Ist kein Shape selektiert, so ist dieser Knopf ausgegraut und damit
+	nicht verfügbar.
+	Dieses Werkzeug ist besonders für den Fall hilfreich wenn man Objekte
+	in einer Ebenen-Tabelle auswählt und sie auf der Karte schnell
+	anspringen machen möchte.
+    	</para>
+	</listitem>
+	</itemizedlist>
+  	</section>
+
+  	<section><title>Objekt Identifikation</title>
+    	<para>
+        Objekte auf der Karte können identifiziert werden über das Identifikations-Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_3_identify.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_3_identify.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Identifikations-Werkzeug</phrase> </textobject>
+        </inlinemediaobject>.
+        Klickt man auf ein Objekt wird es selektiert und es wird ein
+	Dialog geöffnet der dann alle Tabellenattribute für das Objekt
+	anzeigt. Jegliche vorherige Selektion wird gelöscht.
+	Objekte auf der Karte sind typischerweise Shapes und dieses
+	Dokument wird sich häufiger auf Objekte als Shapes beziehen. 
+    	</para>
+  	</section>
+
+  	<section><title>Objekt mit Label versehen</title>
+    	<para>
+        Objekte können über das Label-Werkzeug mit Labeln versehen
+	werden
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_3_label.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_3_label.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Label Werkzeug</phrase> </textobject>
+        </inlinemediaobject>.
+        Klickt man auf ein Objekt, so wird dies selektiert und es wird ein
+	Dialog geöffnet welcher dessen Attribute darstellt.
+	Eins der Attribute kann nun als Label für das Objekt auf der Karte
+	ausgewählt werden. Der Label wird dann mittif auf dem Shape
+	plaziert.
+	Klickt man auf ein Objekt welches bereits ein
+	Label hat, so wird dieser nun entfernt.
+    	</para>
+  	</section>
+
+  	<section><title>Die Legende</title>
+        <para>
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_legend.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_legend.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Legende</phrase> </textobject>
+        </inlinemediaobject>
+        </para>
+    	<para>
+        Die Legende bietet eine Übersicht über die Ebenen der Karte.
+	Ebenen die weiter oben in der Legende stehen sind
+	``näher'' zum Benutzer.
+        Falls eine Ebene Klassifizierung unterstützt (derzeit haben
+	nur Shape-Ebenen haben diese Eigenschaft) so werden die Gruppen
+	der Klassifikation für jede Ebene dargestellt. 
+        Die Eigenschaften für jede Gruppe werden auch als kleine Grafiken
+	dargestellt. Polygon-Ebenen werden als Rechtecke dargestellt,
+	Linoen als Kurven und Punkte als Kreise.
+        </para>
+        <para>
+        Am oberen Rand der Legende ist eine Werkzeugleiste welche einen schnellen
+	Zugriff auf einige der Komanndos des Menüs
+        <menuchoice><guimenu>Map</guimenu></menuchoice>
+	gestattet. 
+        </para>
+
+	<itemizedlist>
+	<listitem>
+        <para>
+        Das Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_totop.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_totop.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Auf die oberste Ebene bewegen</phrase> </textobject>
+        </inlinemediaobject> bewegt die selektierte Ebene auf der Karte
+	nach ganz oben.
+        </para>
+	</listitem>
+	<listitem>
+
+        <para>
+        Das Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_moveup.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_moveup.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Eine Ebene nach oben bewegen</phrase> </textobject>
+        </inlinemediaobject> bewegt die selektierte Ebene um einen
+	Schritt nach oben.
+        </para>
+	</listitem>
+	<listitem>
+
+        <para>
+        Das Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_movedown.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_movedown.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Eine Ebene nach unten bewegen</phrase> </textobject>
+        </inlinemediaobject> bewegt die selektierte Ebene um einen Schritt
+	nach unten.
+        </para>
+
+	</listitem>
+	<listitem>
+        <para>
+        Das Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_tobottom.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_tobottom.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Auf die unterste Ebene bewegen</phrase> </textobject>
+        </inlinemediaobject> bewegt die selektierte Ebene auf
+	der Karte nach ganz unten.
+        </para>
+
+	</listitem>
+	<listitem>
+        <para>
+        Das Sichtbarkeits-Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_visible.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_visible.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Sichtbar</phrase> </textobject>
+        </inlinemediaobject> sorgt dafür, dass eine vorher nicht sichtbare
+	Ebene nun wieder in der Karte dargestellt wird.
+        </para>
+
+	</listitem>
+	<listitem>
+        <para>
+        Das Unsichtbar-Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_invisible.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_invisible.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Unsichtbar</phrase> </textobject>
+        </inlinemediaobject> versteckt die aktuell
+	selektierte Ebene auf der Karte.
+        </para>
+
+	</listitem>
+	<listitem>
+        <para>
+        Das Eigenschaften-Werkzeug
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_props.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_props.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Eigenschaften</phrase> </textobject>
+        </inlinemediaobject> startet den Eigenschaften-Dialog für die
+	aktuelle Ebene.
+	Ein Doppel-Klick auf eine Ebene startet ebenfalls diesen Dialog.
+    	</para>
+	</listitem>
+	</itemizedlist>
+
+	<para>
+	Die am häufigsten benötigten Aktionen zu den Ebenen sind
+	über ein Popup-Menü erreichbar. Es erscheint wenn Sie
+	mit der Maus über einer Ebene stehen und die rechten
+	Maustaste betätigen.
+	</para>
+	
+	<para>
+        <figure>
+        <title>Popup Menü für Ebenen</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/3_5_popup_menu.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/3_5_popup_menu.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+
+        <para>
+        Am unteren Rand der Legende befindet sich
+	die Maßstabsanzeige. Sie ist immer dann zu sehen wenn
+	für die Karte eine Projektion gesetzt ist und mindestens
+	eine Ebene vorhanden ist.
+        </para>
+  	</section>
+
+  	<section><title>Exportieren</title>
+        <para>
+        Auf dem Betriebssystem MS Windows können Karten im Enhanced Metafile Format
+        (<varname>.wmf</varname>)
+        über 
+        <menuchoice>
+        <guimenu>Karte</guimenu>
+        <guimenuitem>Export</guimenuitem>
+        </menuchoice> erstellt werden um sie in Reports,
+	Präsentationen oder weitergehenden Bearbeitungen zu verwenden.
+        Die aktuelle Kartenansicht, Legende und, falls verfügbar,
+	Maßstabsanzeige werden dafür exportiert.
+        Auf anderen Plattformen steht dies nicht zur
+	Verfügung.
+        Wählt man diesen Menüpunkt an so wird ein
+	Dateiauswahldialog für die zu erstellende Exportdatei
+	geöffnet.
+        </para>
+  	</section>
+
+  	<section><title>Drucken</title>
+    	<para>
+        Eine Karte wird über 
+        <menuchoice>
+        <guimenu>Karte</guimenu>
+        <guimenuitem>Drucken</guimenuitem>
+        </menuchoice> ausgedruckt. Die aktuelle Kartenansicht, Legende und,
+	falls vorhanden, die Maßstabsanzeige werden gedruckt.
+        Es wird ein Standard-Druckdialog geöffnet der die Konfiguration
+	des Druckers gestattet. Dieser Druckdialog unterscheidet sich je
+	nachdem auf welcher Plattform Thuban ausgeführt wird.
+    	</para>
+  	</section>
+
+  </chapter>
+
+  <chapter><title>Ebenen Management</title>
+    <para>
+    </para>
+
+  	<section><title>Typen von Ebenen</title>
+    	<para>
+        Thuban unterstützt 3 Typen von Ebenen:
+	Shape-Ebenen, Datenbank-Ebenen und Bild-Ebenen.
+        Shape-Ebenen bestehen aus vektor-basierten Objekten mit
+	geo-referenzierten Koordinaten.
+	Es werden drei Shape-Typen unterstützt:
+        Polygone, Linien und Punkte.
+	Datenbank-Ebenen sind den Shape-Ebenen ähnlich und unterscheiden
+	sich darin, dass die Daten aus einer Datenbank geholt werden
+	anstatt direkt vom Dateisystem.
+	Bild-Ebenen können im Prinzip alle von GDAL unterstützten Dateiformate
+	sein. GDAL ist eine externe Bibliothek und steht für
+        Geo-spatial Data Abstraction Library.
+        Das Bild muss Informationen zu seiner geographische Lage und
+	Ausdenung beinhalten, entweder direkt in die Datei eingebettet
+	oder als separate Datei im selben Verzeichnis wie die Bild-Datei.
+        GeoTIFF Dateien funktionieren sehr gut mit Thuban und sind
+	speziell als Bildebenen für Bild-Ebenen bei Geographischen
+	Informationssystemen geeignet.
+    	</para>
+        <para>
+        Alle Aktionen im Menü
+        <menuchoice>
+        <guimenu>Ebene</guimenu>
+        </menuchoice> beziehen sich auf die in der Legende aktuell
+	ausgewählten Ebene.
+        </para>
+  	</section>
+
+  	<section><title>Eigenschaften</title>
+    	<para>
+        Um die Eigenschaften einer Ebene anzusehen muss zunächst eine Ebene
+	in der Legende selektiert werden.
+        Die Menüoption
+        <menuchoice>
+        <guimenu>Ebene</guimenu>
+        <guimenuitem>Eigenschaften</guimenuitem>
+        </menuchoice> öffnet einen Dialog zu den Eigenschaften
+	der Ebene.
+        Alle Ebenen haben einen Titel der hier entsprechend geändert werden kann.
+        Der Typ der Ebene ist ebenfalls ersichtlich.
+	Handelt es sich um einen Shape-Typ (Polygon, Linie, Punkt) so
+	wird eine Tabelle für Klassifizierung dargestellt.
+        Bildebenen haben keineweiteren Eigenschaften als
+	den Titel und Typ.
+    	</para>
+        <para>
+        <figure>
+        <title>Eigenschaften Fenster</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/4_2_layer_properties.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/4_2_layer_properties.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+    	</para>
+        <para>
+        <figure>
+        <title>Eigenschaften Fenster</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/4_2_raster_layer_properties.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/4_2_raster_layer_properties.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+    	</para>
+  	</section>
+
+  	<section><title>Sichtbarkeit</title>
+    	<para>
+        Manchmal ist es nicht erwünscht alle Ebenen gleichzeitig anzuzeigen.
+	Einige Ebenen könnten etwas länger für den Aufbau brauchen, was
+	z.B. störend bei schneller Navigation ist.
+	Jede Ebene kann einzeln an- oder ausgeschaltet werden mit
+        <menuchoice>
+        <guimenu>Ebene</guimenu>
+        <guimenuitem>Zeigen</guimenuitem>
+        </menuchoice>
+        bzw.
+        <menuchoice>
+        <guimenu>Ebene</guimenu>
+        <guimenuitem>Verstecken</guimenuitem>
+        </menuchoice>.
+    	</para>
+  	</section>
+
+  	<section><title>Duplizierung</title>
+    	<para>
+        Ebenen mit allen Eigenschaften inklusive Klassifikation
+	können dupliziert werden mit
+        <menuchoice>
+        <guimenu>Ebene</guimenu>
+        <guimenuitem>Duplizieren</guimenuitem>
+        </menuchoice>. Die Duplizierung von Ebenen ist sinnvoll
+	z.B. wenn eine Ebene auf verschiedene Weise modelliert werden
+	soll. Obwohl sich die Ebenen direkt überlagern ist es
+	durch sinnvolle Einstellung der Shape Eigenschaften möglich
+	mehrer Aspekte gleichzeitig zu visualisieren.
+        Beispielsweise kann eine Kopie einer Strassen-Ebene
+	bezüglich der Länge klassifiziert sein und eine
+	weitere Kopie bezüglich Strassen-Typ.
+	Wenn dann die Länge durch Farbe und der Typ durch Linienbreite
+	gesetzt wird, dann ist es möglich beide Eigenschaften zu
+	visualisieren indem die Kopie für den Typ über die Kopie mit
+	der Länge gelegt wird.
+    	</para>
+  	</section>
+
+  </chapter>
+
+  <chapter><title>Ebenen-Klassifizierung</title>
+    <para>
+    Die Klassifizierung einer Ebene bedeutet das zuordnen von
+    Zeichenvorschriften zu Shape-Gruppen basierend auf deren Attributen
+    die in zur Ebene gehörenden Tabelle gespeichert sind.
+    Es können daher auch nur Shape-Ebenen klassifiziert werden und
+    keine Bild-Ebenen.
+    </para>
+    <para>
+    Eine Klassifizierung besteht aus mehreren Grupppen. Jede Gruppe
+    hat einen einzelnen Wert oder einen Wertebereich auf den hin
+    verglichen wird. Ausserdem hat jede Gruppe eine Zeichenvorschrift
+    welche bestimmt wie die zugehörigen Shapes dargestellt werden
+    sollen.
+    Der Anwender gibt an welches Feld der Tabelle für Klassifizierung
+    verwendet werden soll. Wird die Karte dann gezeichnet so
+    wird für jedes Shape der entsprechende Wert aus der Tabelle
+    geholt und mit den definierten Gruppen-Wertebereichen
+    verglichen. Es werden dann die Zeichenvorschriften
+    derjenigen Gruppe benutzt, welche als erstes beim Vergleich
+    passte.
+    Dies gestattet es einen visuellen Eindruck z.B.
+    der räumlichen Verteilung von Objekten mit
+    bestimmten Eigenschaften zu erhalten.
+    </para>
+    <para>
+    Eine Ebene hat grundsätzlich eine Klassifizierung.
+    Wird zur Karte eine neue Ebene hinzugefügt,
+    wird sie mit einer vordefinierten Klassifizierung
+    versehen. Diese besteht nur aus der einen Gruppe DEFAULT.
+    Diese Gruppe kann man nicht entfernen, lässt sich aber
+    verstecken (siehe unten).
+    Jedes Shape der Ebene, unabhängig von dessen Attributen, wird
+    diese Gruppe zugeordnet, falls nicht vorher eine andere passt.
+    </para>
+
+  	<section><title>Klassifizierung bearbeiten</title>
+    	<para>
+        Die Klassifizierung für eine Ebene wird über den Eigenschaftendialog
+	bearbeitet
+        (<menuchoice>
+        <guimenu>Ebene</guimenu>
+        <guimenuitem>Eigenschaften</guimenuitem>
+        </menuchoice>). Das Feld für die Klassifizierung der Ebene kann ugesetzt sein.
+	In diesem Fall wird die Gruppe DEFAULT als Klassifizierung eingesetzt.
+        Solange kein Feld gesetzt wird kann keine weiter Gruppe zur
+	Klassifizierung hinzugefügt werden.
+	Es muss also zunächst ein Feld ausgewählt werden. Dann können
+	weitere Gruppen mit dem Knopf
+        <guibutton>Hinzufügen</guibutton> in die Klassifizierung aufgenommen
+	werden.
+        </para>
+        <para>
+        Um die Änderungen auf die Karte anzuwenden kann der Benutzer
+	entweder <guibutton>Anwenden</guibutton> oder
+	<guibutton>OK</guibutton> verwenden.
+        <guibutton>Anwenden</guibutton> schliesst dabei den Dialog
+	nicht, sondern gestattet es, die gemachten Änderungen auf der
+	Karte als Voransicht zu sehen.
+        <guibutton>Zurücksetzen</guibutton> setzt die zuletzt angewendete
+	Klassifikation zurück.
+        <guibutton>OK</guibutton> wendet die Änderungen an
+	und schliesst den Dialog. Dann können die Änderungen
+	nicht mehr zurückgenommen werden.
+        <guibutton>Schliessen</guibutton> beendet den Dialog.
+	Alle Änderungen, die nicht mit <guibutton>Anwenden</guibutton> auf
+	die Karte gebracht wurden, werden verworfen. 
+        </para>
+        <para>
+        <figure>
+        <title>Eigenschaften Fenster</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_classification.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_classification.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+        <para>
+        Die Reihenfolge der Gruppen in der klassifizierung ist
+	von Bedeutung. Eine Ausnahme bildet die Gruppe DEFAULT,
+	welche immer ganz oben verbleibt.
+	Werden die Shapes den Gruppen zugeordnet, so beginnt
+	der Vergleich mit der ersten Gruppe nach DEFAULT und dann
+	absteigend.
+        Der Vergleich endet sobald eine Gruppe für das Shape passt.
+        Mit <guibutton>Eine Ebene nach oben bewegen</guibutton> und
+	<guibutton>Eine Ebene nach unten bewegen</guibutton>
+        wird die Reihenfolge der Gruppen geändert.
+	Die Gruppe DEFAULT wird uaf alle Shapes angewandt die
+	auf keine der anderen Gruppen passssen.
+    	</para>
+  	    <section><title>Sichtbar</title>
+    	    <para>
+            Die Spalte Sichtbar beinhaltet Ankreuzfelder mit denen
+	    bestimmt werden kann ob die Gruppen auch in der
+	    Legende dargestellt werden sollen.
+            Das ist zum Beispiel hilfreich wenn die Gruppen alle
+	    Shapes abdecken und daher die Gruppe DEFAULT nicht
+	    in der Legende bzw. im Ausdruck auftauchen soll.
+            </para>
+        </section>
+  	    <section><title>Symbole</title>
+    	    <para>
+            Jeder Shape-Typ hat seinen eigenen Symbol-Typ.
+	    Thuban unterstützt 3 Shape-Typen: Polygone, Linien und Punkte.
+            Polygone und Punkte haben eine Rand- und Füllfarbe, Linien
+	    haben nur eine Linienfarbe.
+            zu jeder Gruppe gehören Symbol-Eigenschaften.
+            Um diese zu bearbeiten, kann man entweder einen Doppelclick
+	    auf das Symbol machen oder die entsprechende Gruppe
+	    selektieren und dann den Knopf
+            <guibutton>Symbol bearbeiten</guibutton> verwenden.
+    	    </para>
+  	    </section>
+        <section><title>Wert</title>
+            <para>
+            Die Spalte Wert enthält die Werte auf die die Shapes
+	    verglichen werden wenn die Karte gezeichnet wird.
+            Die Art der Angaben in diesen Feldern hängt vom
+	    Typ der Daten des Klassifizierungs-Feldes.
+            </para>
+            <para>
+            Ist das Feld vom Typ Text, sind beliebige Eingaben erlaubt.
+            Der Text wird buchstabenweise mit dem Wert des Shape-Attributes
+	    verglichen. Gross-Kleinschreibung wird dabei berücksichtigt.
+            Ist das Feld vom Typ Integer, sind alle ganzen Zahlen
+	    erlaubt. Darüber hinaus können auch mit spezieller Syntax
+	    Bereiche angegeben werden.
+            Ein Bereich von <varname>start</varname> bis
+	    <varname>ende</varname> inklusive der Grenzen wird so
+	    eingegeben: <literal>[start;ende]</literal>.
+            Der Bereich ohne die Grnezen wird so angegeben:
+            <literal>]start;ende[</literal>. Bereich können auch
+	    Unendlich als Wert benutzen: <literal>[-oo;oo]</literal>.
+	    Der Feld-Typ kann auch Dezimal sein. Dann können beliebeige
+	    rationale Zahlen verwendet werden.
+            </para>
+  	    </section>
+  	    <section><title>Label</title>
+    	    <para>
+            
+	    
+	    als Voreinstellung wird als Label für die Gruppe in der
+	    Legende der Wert verwendet. Es kann aber auch ein spezieller
+	    Label angegeben werden.
+            </para>
+        </section>
+  	</section>
+
+  	<section><title>Erzeuge Klassifikation</title>
+    	<para>
+        <figure>
+        <title>Erzeuge Klasse</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_3_genclass.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_3_genclass.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+    	</para>
+    	<para>
+        Das manuelle erstellen eine Klassifikation
+	kann anstrengend werden.
+        Thuban bietet hier die Möglichkeit, Klassikationen
+	automatisch, aber unter Kontrolle des Benutzers, zu
+	erstellen.
+        Clicked man auf <guibutton>Erzeuge Klasse</guibutton>
+        so wird der Dialog <varname>Erzeuge Klassifikationn</varname>
+	geöffnet.
+        Unter dem Aufklappmenü <varname>Erzeuge</varname> finden sich
+	in der Regel drei unterschiedliche Arten für die
+	Erzeugung von Klassifikationen:
+        Eindeutige Werte, Gleichförmige Verteilung und Quantile.
+	Einige Optionen sind nicht verfügbar wenn der Datentyp
+	des Feldes es nicht unterstützt.
+        So macht beispielsweise <varname>Gleichförmige Verteilung</varname>
+        keinen Sinn bei Text-Feldern.
+    	</para>
+        <para>
+        In jedem Fall muss bei der Erzeugung einer Klassifizierung
+	ein Farbschema ausgewählt werden.
+        Thuban bietet einige verschiedene Farb-Schemata die dann bestimmen
+	wie sich Gruppeneigenschaften über die Klassifizierung ändern.
+        Es mag gewünscht sein, dass nur bestimmte Eigenschaften
+	sich über die Klassifizierung ändern.
+        Ist der Shape-Typ Polygon oder Punkt, so die Option
+        <guibutton>Rahmenfarbe festlegen</guibutton> verfügbar.
+        Diese erlaubt es, eine feste Rahmenfarbe für alle
+	Gruppen der Klassifizierung festzulegen.
+        Es ist ebenfalls möglich ein benutzerdefiniertes Farbschema
+	zu erstellen.
+	Wählt man diese Option aus, werden zwei Symbole
+	dargestellt: das linke Symbol hat die Eigenschaften für
+	die erste Gruppe, das rechte für die letzte Gruppe.
+        Thuban interpoliert dann zwischen diesen beiden um die
+	Eigenschaften für die enderen Gruppen zu erstellen.
+        <figure>
+        <title>Benutzerdefiniertes Farbschema</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_2_custom_ramp.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_2_custom_ramp.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+        <para>
+        Die Option Eindeutige Werte erlaubt es, spezielle Werte
+	auszuwählen die in der Tabelle vorkommen.
+        Clickt man <guibutton>Aus Tabelle holen</guibutton>
+        so wird die Tabelle nach allen vorkommenden Werten
+	durchsucht und diese in der Liste auf der linken Seite dargestellt.
+        Beide Listen für eine schnellere Suche sortiert
+	oder umgedreht werden.
+        Die Klassifizierung die dann erzeugt wird
+	wird dieselbe Sortierung wie die rechte Liste haben.
+        <figure>
+        <title>Eindeutuige Werte</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_2_unique_values.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_2_unique_values.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+        <para>
+        Die Option Gleichförmige Verteilung erzeugt die angegebene
+	Anzahl von Gruppen mit Bereichen wobei alle Bereiche
+	das gleiche Intervall haben.
+        Minimum und Maximum hierfür können automatisch aus der Tabelle
+	ermittelt werden indem die Option 
+        <guibutton>Aus Tabelle holen</guibutton> verwendet wird.
+	Die Stufen bestimmen die Grösse des Intervalls.
+        Ändert man diesen Wert, wird automatisch neu berechnet
+	wie viele Gruppen nun passend sind.
+        <figure>
+        <title>Gleichförmige Verteilung</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_2_uniform_dist.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_2_uniform_dist.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+        <para>
+        Die Option Quantile erzeugt Bereiche anhand der Anzahl Elemente in
+	der Tabelle.
+        Beispielsweise werden durch die Wahl von fünf Gruppen
+	entsprechend fünf Gruppen mit passenden Bereichen erstellt,
+	so dass 20% der Tabellendaten in jeder Gruppe enthalten sind.
+        Ist es nicht möglich exakte Gruppierungen zu erzeugen,
+	sow wird Thuban Warnung mitteilen aber die Aktion fortführen.
+        <figure>
+        <title>Quantile</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_2_quantiles.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_2_quantiles.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+  	</section>
+  </chapter>
+
+  <chapter><title>Projektions-Management</title>
+    <para>
+    Projektionen bestimmen wie geographische Daten auf dem
+    Bildschirm dargestellt werden.
+    Werden mehrere Ebenen in Thuban geladen bei denen die
+    geographischen Daten in verschiedenen Projektionssystemen
+    vorliegen, so muss jeder Ebene die entsprechende Projektion
+    zugeordnet sein. Ebenso muss eine Projektion für die Karte
+    angegeben werden.
+    Dies kann die gleiche wie die der Ebenen sein oder eine
+    andere Projektion wobei dann die Ebenen entsprechend
+    umprojeziert werden.
+    Die Projektion der Karte wird über
+    <menuchoice>
+    <guimenu>Karte</guimenu>
+    <guimenuitem>Projektion</guimenuitem>
+    </menuchoice> und die Projektionen für die Ebenen über
+    <menuchoice>
+    <guimenu>Ebene</guimenu>
+    <guimenuitem>Projektion</guimenuitem>
+    </menuchoice> gesetzt.
+    <figure>
+    <title>Projektionsauswahl-Fenster</title>
+    <mediaobject>
+    <imageobject><imagedata fileref="../images/6_projection.png" format="PNG" scale="&imgscale;"/></imageobject>
+    <imageobject><imagedata fileref="./images/6_projection.eps" format="EPS" scale="&imgscale;"/></imageobject>
+    </mediaobject>
+    </figure>
+    </para>
+    <para>
+    Thuban kommt mit eine Beispiel-Sammlung von Projektionen sowie
+    dem von der EPSG (European Petroleum Survey Group) Satz. Dieser
+    recht umfangreiche Satz wird nur angezeigt wenn er durch das entsprechende
+    Wahlfeld eingeschaltet wurde.
+    Der Satz besteht aus zwei Gruppen, die Liste der veralteten Projektionen
+    enthält diejenigen Projektionen die eine EPSG Nummer haben aber
+    in der aktuellen EPSG Datenbank nicht mehr enthalten sind.
+    </para>
+    <para>
+    Ein Benutzer kann neue Projektionen definieren und sie für zukünftige
+    Thuban Sitzungen zugängig machen. Sie können auch exportiert
+    und importiert werden, so dass spezielle Projektionen
+    leicht weitergegeben werden können.
+    </para>
+  	<section><title>Eine Projektion auswählen</title>
+        <para>
+        Die verfügbaren Projektionen sind link aufgelistet.
+	Hat die Ebene oder Karte bereits eine Projektion,
+	so ist diese zunächst hervorgehoben und trägt den Hinweis
+        <varname>(aktuell)</varname>. Wird 
+        <varname>&lt;Keine&gt;</varname> ausgwählt, so wird Thuban die Daten
+	dirket verwenden wie sie in den Quellen vorkommen und keine
+	Umprojezierung vornehmen.
+        </para>
+    </section>
+  	<section><title>Eine Projektion bearbeiten</title>
+        <para>
+        Immer wenn eine Projektion aus der Liste ausgwählt wird, dann
+	werden deren konkrete Eigenschaften rechts dargestellt.
+	Diese Eigenschaften können geändert werden und die Änderungen
+	in der Projektion über <guibutton>Aktualisieren</guibutton>
+	gespeichert werden.
+        Es können ausschliesslich Projektionen aktualisiert
+	werden, die aus einer Datei kommen.
+	Wenn also die Projektion der aktuellen Ebene angewählt ist, so
+	ist die Aktion <guibutton>Aktualisieren</guibutton> deaktiviert.
+        <guibutton>Hinzufügen zur Liste</guibutton> fügt die Projektion
+	an die Liste der verfügbaren Projektionen an und macht sie so
+	auch in zukünftigen Thuban Sitzungen verfügbar.
+        Mit <guibutton>Neu</guibutton> wird eine neue, leere Projektion
+	erzeugt.
+        Die Aktion <guibutton>Entfernen</guibutton> löscht eine
+	Projektion dauerhaft aus der Liste.
+        </para>
+        <para>
+        Um eine Projektion auf die Karte anzuwenden kann man
+        <guibutton>Anwenden</guibutton> oder <guibutton>OK</guibutton>
+	benutzen.
+        <guibutton>Anwenden</guibutton> schliesst den Dialog nicht
+	und erlaubt es so, die Änderung auf der Karte zunächst zu begutachten.
+        <guibutton>Zurücksetzen</guibutton> macht die zuletzt gemachte
+	Änderung wieder rückgängig.
+        <guibutton>OK</guibutton> aktiviert die gemachten Änderung und
+	schliesst den Dialog.Danach kann man diese Änderung nicht mehr
+	rückgängig machen.
+        <guibutton>Schliessen</guibutton> beendet den Dialog.
+	Wurde bis dahin keine Projektion mit
+        <guibutton>Anwenden</guibutton> ausprobiert, so wird sie auch
+	nicht auf die Karte übertragen.
+        </para>
+    </section>
+  	<section><title>Projektionen Importieren/Exportieren</title>
+        <para>
+	Projektionen die in der Liste verfügbaren Projektionen auftauchen
+	können in eine Datei exportiert werden.
+	Nach der Auswahl einer oder mehrerer Projektionen wird nach betätigen von
+        <guibutton>Export</guibutton> ein entsprechender
+	Dateiauswahldialog gestartet.
+	Die Datei kann dann z.B. an andere Thuban-Anwender weitergegeben
+	werden.
+        Um eine solche Datei zu importieren verwendet man die Aktion
+        <guibutton>Import</guibutton>.
+        Die importierten Projektionen werden zur Liste verfügbarer
+	Projektionen zur sofortigen oder späteren Verwendung hinzugefügt.
+        </para>
+    </section>
+  </chapter>
+
+  <chapter><title>Tabellen-Management</title>
+    <para>
+    Thuban unterscheidet zwei unterschiedliche Tabellen-Typen:
+    Attributtabellen (welche zu einer Ebene gehört) sowie normale
+    Datentabellen.
+    Beide bieten die gleiche allgemeine Funktionalität mit dem
+    einzigen Unterschied, dass Aktionen auf einer Attributtabelle
+    die Kartendarstellung ändern können.
+    </para>
+
+    <section><title>Tabellen-Ansicht</title>
+        <para>
+        <figure>
+        <title>Tabellen-Ansicht</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/7_1_table_view.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/7_1_table_view.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+        <para>
+	Thuban stellt einen Standard-Dialog für die Anzeige einer Tabelle
+	zur Verfügung. Diese Aansicht hat 5 Elemente:Titel, Selektion,
+	das Tabellenraster, Exportfunktionen und die Statuszeile.
+        </para>
+        <para>
+        Die Titelzeile identifiziert die Tabelle mit ihrem Namen.
+        </para>
+        <para>
+        Die Selektionsbox erlaubt es dem Benutzer einfache Analysen auf den Daten
+	durch Vergleiche durchzuführen: Die erste Auswahl ist ein Feldbezeichner
+	der Tabelle, die zweite Auswahl bestimmt den Typ des Vergleichs.
+	Die dritte Auswahl kann entweder ein bestimmter Wert (interpretiert
+	als Zahl oder als Zeichenkette abhängig vom Typ des ersten Feldes)
+	oder ein zweiter Feldbezeichner sein.
+	D.h. man kann Analysen durchführen wie alle Einträge auswählen bei
+	denen <literal>bevoelkerung > 10000</literal> oder 
+        <literal>pkw_pro_einwohner < fahrraeder_pro_einwohner</literal> 
+        (beachten Sie, dass die Namen nur exemplarisch sind, dBase Dateien
+	erlauben nur Bezeichner mit einer maximalen Länge von 11 Zeichen).
+      
+        Selektionen können kombiniert werden. Entweder bezieht sich
+	die Selektion auf die zuvor selektierten Einträge oder man kann
+	eine bestehende Selektion erweitern. Voreingestellt ist
+	einersetzen der bisherigen Selektion.
+        </para>
+        <para>
+        Das Tabellenraster zeigt den Inhalt der Tabelle (pro Zeile ein Eintrag).
+	Selektionen sind hervorgehoben. Die Grösse der Zeiken und Spalten kann
+	verändert werden.
+        </para>
+        <para>
+	Der Inhalt einer Tabelle kann in eine Datei exportiert werden,
+	entweder im dBase format (DBF) oder als kommaseparierte Werte
+	(CSV). Der.
+        <guibutton>Export</guibutton> Knopf startet einen Dialog
+	zur Angabe des Pfades und des Namens der Datei.
+	Der Export-Typ wird durch die Namenserwiterung spezifiziert
+	(entweder .dbf oder .csv).
+
+        Der Knopf <guibutton>Exportiere Selektion</guibutton> funktioniert
+	ähnlich, exportiert aber nur die aktuelle Selektion.
+
+        Der <guibutton>Schliessen</guibutton> Knopf schliesst das
+	Fenster mit der Tabellenansicht. Dies ist nicht zu verwechseln mit
+	dem Menüpunkt
+        <menuchoice>
+        <guimenu>Tabelle</guimenu>
+        <guimenuitem>Schliessen</guimenuitem>
+        </menuchoice> welcher die Tabelle aus Thuban entfernt.
+        </para>
+        <para>
+        Die Statuszeile zeigt einige statistische Informationen zu
+	der Tabelle sowie zu Selektionsergebnisse an.
+        </para>
+    </section>
+
+    <section><title>Allgemeine Funktionalität (Menü Tabelle)</title>
+        <para>
+	Die allgemeinen Funktionen wirken sich auf alle geöffneten Tabellen
+	aus. Attributtabellen werden wie normale Tabellen behandelt (mit der
+	Ausnahme dass diese nicht geschlossen werden können).
+        </para>
+        <section><title>Öffnen</title>
+            <para>
+            Der Menüpunkt 
+            <menuchoice>
+            <guimenu>Tabelle</guimenu>
+            <guimenuitem>Öffnen</guimenuitem>
+            </menuchoice>
+	    startet einen Dateiselektionsdialog für die Auswahl 
+	    einer dBase-Datei. Diese wird als nur-lesbar in Thuban
+	    geladen.
+            Mit <guibutton>OK</guibutton> wird die ausgewählte Datei
+	    geladen und eine entsprechende Tabellenansicht geöffnet.
+            </para>
+        </section>
+
+        <section><title>Schliessen</title>
+            <para>
+            Der Menüpunkt 
+	    <menuchoice>
+            <guimenu>Tabelle</guimenu>
+            <guimenuitem>Schliessen</guimenuitem>
+            </menuchoice>
+            startet einen Dialog welcher alle derzeit geöffneten Datentabellen
+            (die geladen wurden über 
+            <menuchoice>
+            <guimenu>Tabelle</guimenu>
+            <guimenuitem>Öffnen</guimenuitem>
+            </menuchoice>).
+	    Die gewählten Tabellen werden nach Bestätigung aus Thuban
+	    entfernt.
+	    Da die Tabellen als nur-lesend geöffnet wurden, wird
+	    der Inhalt der Tabellen nicht verändert.
+
+	    Sämtliche offenen Tabellenansichten für diese
+	    Tabellen werden ebenfalls geschlossen.
+
+            Tabellen die bei Verknüpfungen verwendet werden
+	    können nicht geschlossen werden.
+            </para>
+        </section>
+
+        <section><title>Umbenennen</title>
+            <para>
+            <menuchoice>
+            <guimenu>Tabelle</guimenu>
+            <guimenuitem>Umbenennen</guimenuitem>
+            </menuchoice> ändert den Tabellentitel.
+            </para>
+        </section>
+
+        <section><title>Anzeigen</title>
+            <para>
+            Der Menüpunkt
+            <menuchoice>
+            <guimenu>Tabelle</guimenu>
+            <guimenuitem>Anzeigen</guimenuitem>
+            </menuchoice> 
+            öffnet einen Dialog mit der Liste der verfügbaren
+	    Tabellen (explizit geladene Tabellen, Attributtabellen,
+	    Ergebnisse aus Verknüpfungen).
+            Die ausgewählten Tabellen werden nach der
+	    Bestätigung mit
+            <guibutton>OK</guibutton> in Tabellenansichten dargestellt.
+            </para>
+        </section>
+
+        <section><title>Verbinden</title>
+            <para>
+            <figure>
+            <title>Verbinde Tabellen</title>
+            <mediaobject>
+            <imageobject><imagedata fileref="../images/7_2_5_join.png" format="PNG" scale="&imgscale;"/></imageobject>
+            <imageobject><imagedata fileref="./images/7_2_5_join.eps" format="EPS" scale="&imgscale;"/></imageobject>
+            </mediaobject>
+            </figure>
+            </para>
+            <para>
+            Der Menüpunkt
+            <menuchoice>
+            <guimenu>Tabelle</guimenu>
+            <guimenuitem>Verbinden</guimenuitem>
+            </menuchoice> 
+            startet einen Dialog für die Angabe der beiden Tabellen die
+	    verbunden werdn sollen. Das Ergebnis der Verbindung ist eine
+	    neue Tabelle mit der Bezeichnung 
+            'Join of "linke Tabelle" and "rechte Tabelle"'.
+
+            Der Dialog erlaubt es die beiden zu verbindenden Tabellen sowie
+	    die beiden Felder anzugeben über die die Verbindung hergestellt
+	    werden soll. Als Voreinstellung beinhaltet die neue Tabelle
+	    nur die Einträge für die entsprechende Übereinstimmungen
+	    vorlagen.
+
+            Wollen Sie die Einträge der linken Tabelle erhalten, so können
+	    Sie eine äussere Verbindung erstellen. Die Felder der rechten
+	    Tabelle für Einträge ohne Übereinstimmung werden in diesem
+	    Fall aufgefüllt mit dem Wert <varname>None</varname>.
+            </para>
+        </section>
+
+    </section>
+    <section><title>Attribut-Tabellen</title>
+        <para>
+	Um klarer zwischen den beiden Tabellen-Typen (Daten und Attribute) zu
+	unterscheiden, bietet Thuban die Funktionalität für die Attribut-Tabellen
+	unter dem Menü
+        <menuchoice><guimenu>Ebene</guimenu></menuchoice> an. 
+        </para>
+
+        <section><title>Zeige Tabelle</title>
+            <para>
+            <menuchoice>
+            <guimenu>Ebene</guimenu>
+            <guimenuitem>Zeige Tabelle</guimenuitem>
+            </menuchoice> 
+            öffnet die Attribut-Tabelle für die aktuell aktive Ebene in
+	    einer Tabellenansicht.
+
+            Eine zusätzliche Funktionalität bei diesen Tabellenansichten
+	    ist, dass bei Selektionen die korrespondierenden Objekte
+	    auf der Karte unmittelbar hervorgehoben werden.
+            </para>
+        </section>
+
+        <section><title>Verbinde Tabelle</title>
+            <para>
+	    Anders als beim Verbinden wie oben beschrieben
+            erzeugt dieses Verbinden keine neue Tabelle.
+	    Die Attributtabelle der aktiven Ebene stelllt die linke
+	    Tabelle. Die anderen Tabellen werden an diese angebunden.
+            Das Ergebnis dieser Verbindung steht z.B. für Klassifizierungen
+	    zur Verfügung.
+
+            Daraus folgt auch, dass die Verbindung niemals weniger
+	    Einträge haben als die ursprüngliche Attributtabelle.
+	    Der Benutzer wird gewarnt, falls die recht Tabelle dies
+	    nicht erfüllen kann. In so einem Fall muss eine
+	    äussere Verbindung durchgeführt werden.
+            </para>
+        </section>
+
+        <section><title>Tabellen-Verbindung lösen</title>
+            <para>
+            Wie schon erwähnt kann eine Tabelle nicht geschlossen
+	    werden wenn sie noch bei einer Verbindung verwendet wird.
+            Tabellen die neu aus der Verbindung zweier normaler Tabellen
+	    entstanden sind, können ohne weiteres gelöst werden.
+	    Dies gilt jedoch nicht für Attributtabellen.
+
+            Also müssen Attributtabellen explizit gelöst werden.
+	    Dazu wird das Kommando
+            <menuchoice>
+            <guimenu>Ebene</guimenu>
+            <guimenuitem>Verbindungen lösen</guimenuitem>
+            </menuchoice> 
+            verwendet: Die jeweils zuletzt gemachte Verbindung wird
+	    gelöst.
+            </para>
+        </section>
+    </section>
+  </chapter>
+
+  <chapter><title>Erweiterungen</title>
+  	<para>
+	Thuban ist so konstruiert, dass es leicht
+	erwiterbar ist. Der Begriff Erweiterungen wird
+	als allgemeine Bezeichnung für alles verwendet, was Thuban
+	erweitert.
+	Diese Kapitel gibt eine Einführung in verschiedene Möglichkeiten
+	weitere Funktionalität zu Thuban hinzuzufügen, entweder
+	eigene Entwicklungen oder die von Dritten.
+	</para>
+
+	<section><title>Eigene Erweiterungen über thubanstart.py</title>
+		<para>
+		iNachdem Thuban zum ersten mal gestartet wurde, wird
+		ein Verzeichnis .thuban im Heimatverzeichnis des
+		Benutzers erzeugt.
+		Dort kann die Datei thubanstart.py angelegt werden,
+		die dann beim Start von Thuban importiert wird.
+		Es ist empfehlenswert ausschliesslich import-Kommandos
+		in dieser Datei aufzunehmen und den eigentlichen
+		Programmcode separat zu halten.
+		</para>
+		<para>
+		Die Module die importiert werden müssen entweder
+		über die Pfade in Umgebungsvariablen
+		PYTHONPATH gefunden werden oder direkt
+		im .thuban-Verzeichnis abgelegt sein.
+		</para>
+		<para>
+		Als Beispiel kann man die Datei
+		examples/simple_extensions/hello_world.py
+		aus dem Thuban Quelltext in das persönliche .thuban-Verzeichnis
+		kopieren.
+		Nun kann das Kommando import hello_world in die Datei
+		thubanstart.py aufgenommen werden. Nach dem Start von Thuban
+		wird man dann ein zusätzliches Menü
+		<menuchoice><guimenu>Extensions</guimenu></menuchoice> vorfinden
+		in dem der Unterpunkt für die Hello-World Erweiterung
+		zu sehen ist. Wählt man diesen Punkt aus, so
+		wird die bekannte Hello-World Mitteilung ausgegeben.
+		</para>
+	</section>
+
+	<section><title>Im Thuban-Paket enthaltene Erweiterungen</title>
+		<para>
+		Die hier beschriebenen Erweiterungen sind Teil des Thuban-Paketes,
+		aber nicht automatisch aktiviert.
+		Sie befinden sich im Thuban Installations-Verzeichnis unter
+		<literal>Extensions/</literal>. Man aktiviert sie über
+		PYTHONPATH und import wie im obigen Abschnitt erklärt.
+		Stabile Erweiterungen tauchen unter dem Menü
+		<menuchoice><guimenu>Extensions</guimenu></menuchoice> auf
+		und solche die sich noch im experimentellen Stadium
+		befinden und daher unter Umständen nicht komplett 
+		funktional unter 
+		<menuchoice><guimenu>Experimental</guimenu></menuchoice>.
+		</para>
+
+        <section><title>Stabile Erweiterungen</title>
+            <para>
+            Diese Erweiterungen bieten zusätzliche Funktionalität
+            für Thuban die nicht in Kernanwendung integriert
+            ist. Es wird angenommen, dass keine bedeutenden
+            Fehler mehr enthalten sind.
+            </para>
+            <section><title>gns2shp</title>
+             <para>
+             Dieses Werkzeug konvertiert Daten des
+	     Geospatial Names Server
+             (GNS, siehe <ulink url="http://www.nima.mil/gns"/>)
+             in das Shapefile-Format.
+             Die GNS Webseite bietet den Download die Informationen zu
+	     benannten Orten nach Ländern gruppiert für alle Länder an.
+             Einzige Ausnahme sind die USA für welche die Daten in anderer
+	     Form angeboten werden.
+             </para>
+             <para>
+             Wenn man einen Datensatz herunterlädt und auspackt so erhält
+	     man eine Textdatei mit dem Anhang .txt.
+             Wählt man eine solche Textdatei via gns2shp aus, so
+	     wird ein Shapefile mit dem selben Basisnamen
+	     erzeugt und im gleichen Verzeichnis abgelegt.
+             Danach wird es automatisch in Thuban eingeladen.
+             Die Shapefile Dateien werden nicht automatisch
+	     wieder gelöscht.
+             </para>
+             <para>
+             Das Modul gns2shp.py kann auch auf der Kommandozeile
+	     verwendet werden, z.B. für Stapelverarbeitung.
+             </para>
+             <para>
+             Ein Beispiel (<literal>ls.txt</literal> für Liechtenstein)
+             befindet sich im Verzeichnis
+             <literal>Extensions/gns2shp/test</literal>.
+             </para>
+             </section>
+
+             <section><title>SVG Export</title>
+             <para>
+             Karte und Legende können separat in das Thuban-SVG-Format exportiert
+	     werden.Die erzeugten Dateien entsprechen der
+	     Scalable Vector Graphics (SVG) 1.1 Specification
+             und können von den meisten Vektorzeichenprogrammen gelesen
+	     werden.
+             </para>
+             <para>
+             Ziel des SVG-Export ist es, den Beginn einer
+	     Druck-Kette für Thuban-Karten anzubieten.
+             Für diesen Zweck enthalten die erzeugten Thuban-Karten-SVG Dateien
+	     zusätzliche Informationen welche in einer Nachbearbeitung
+	     verwendet werden können.
+             Typischerweise ist ein Vektorzeichenprogramm wesentlich
+	     mächtiger bei der grafischen Ausgestaltung als eine
+	     Geodaten-Betrachter; z.B. stehen viel mehr Symbole
+	     und Fonts zur Verfügung.
+             Auch unterstützt dies den Anwender darin, aufgabenorientierte
+	     Komponenten jweils sinnvoll auszunutzen.
+             Die Idee ist also, das Zeichenprogramm für die Druckvorbreitung
+	     zu verwenden und nicht das GIS. Die zusätzlichen Informationen
+	     die im Export-Format gespeichert werden ermöglichen es,
+	     dass wenn sich nur einzelne Geo-Objekte ändern
+             das Layout und die Stile für die ganze Karte im Zeichenprogramm
+	     beizubehalten.
+             </para>
+             <para>
+             Markus Rechtien hat den Prototyp dieser
+	     Druckkette im Rahmen einer Diplomarbeit
+	     entwickelt und validierte damit ein
+	     Konzept von Bernhard Reiter.
+             Skripte für entsprechende Weiterverarbeitung
+	     existieren für die Zeichenanwendung Skencil
+             (<ulink url="http://www.skencil.org"/>).
+             </para>
+             <para>
+             Technische Hinweise: die Namen der Ebenen werden
+	     als Basis für IDs im SVG-Format verwendet.
+	     Wenn man versucht, zwei Ebenen mit gleichem Namen
+	     zu exportieren, dann tritt entsprechend ein Fehler auf.
+             Ändern Sie einfach den Namen einer Ebene und versuchen
+	     Sie es erneut.
+             </para>
+             </section>
+         </section>
+
+         <section><title>Experimentelle Erweiterungen</title>
+	<para>
+	Die hier beschriebenen Funktionen sollten mit Vorsicht
+	verwendet werden, da sie nicht vollständig und/oder nicht
+	ausreichend getestet sind.
+	Trotzdem können sie in der Praxis schon recht hilfreich sein.
+	</para>
+	<para>
+	Interesse, diese Erweiterungen zu verbessern sollte
+	auch der Entwickler- und Benutzergemeinschaft
+	mitgeteilt werden.
+	</para>
+
+	<section><title>importAPR</title>
+	<para>
+	Dieses Kommando gestattet es, eine ESRI® ArcView® Projectdatei
+	zu laden (endet auf .apr) und für weitere Nutzung in Thuban
+	zu konvertieren.
+	Nach Auswahl der zu ladenden apr-Datei erscheint eine
+	Auswahlliste mit den enthaltenen Ansichten, falls mehr als
+	eine existiert.
+	Desweiteren wird der Session Infobaum um eine Repräsentation
+	der kompletten apr-Datei erweitert.
+	</para>
+	<para>
+	Die Legende von Thuban deckt nicht alle Elemente die von
+	ArcView® unterstützt werden ab.
+	Daher wird die Karte in Thuban anders aussehen.
+	Zudem ist das apr-Format proprietär und nicht offen dokumentiert.
+	Das bedeutet, dass die Interpretation auf
+	Reverse Engeneering und intelligentem Raten basiert.
+	</para>
+	<para>
+	Die Dateipfade innherhalb der apr-Datei passen unter
+	Umständen nicht und müssen ggf. manuell in der apr-Datei
+	mit einem Texteditor angepasst werden.
+	Die Pfade m:The paths are either absolute
+	or relative from where Thuban has been started.
+	</para>
+	<para>
+	A sample for the Iceland data is included as
+	<literal>Extensions/importAPR/samples/iceland.apr</literal>.
+	The file-paths are relative from the Thuban main directory.
+	</para>
+	</section>
+	</section>
+	</section>
+
+	<section><title>Writing simple extensions</title>
+		<para>
+		Writing an extension for Thuban basically means to
+		implement the extra functionality in Python with all of the
+		Thuban classes, methods and variables available.
+		</para>
+		<para>
+		All classes and their methods are documented in the source code
+		(see their doc-strings). Here is an example from
+		Thuban/Model/layer.py that describes some of the methods
+		of a Layer object:
+		</para>
+		<programlisting>
+		<![CDATA[
+class BaseLayer(TitledObject, Modifiable):
+
+    """Base class for the layers."""
+
+    def __init__(self, title, visible = True, projection = None):
+        """Initialize the layer.
+
+        title -- the title
+        visible -- boolean. If true the layer is visible.
+        """
+        TitledObject.__init__(self, title)
+        Modifiable.__init__(self)
+        self.visible = visible
+        self.projection = projection
+
+    def Visible(self):
+        """Return true if layer is visible"""
+        return self.visible
+
+    def SetVisible(self, visible):
+        """Set the layer's visibility."""
+        self.visible = visible
+        self.issue(LAYER_VISIBILITY_CHANGED, self)
+
+    def HasClassification(self):
+        """Determine if this layer support classifications."""
+...
+		]]>
+		</programlisting>
+		<para>
+		This example intends to give you an impression of the
+		source-code-level documentation.
+		You have to make yourself familiar with
+		the Python programming language to understand some special
+		code elements.
+		</para>
+		<section><title>hello_world.py</title>
+		  <para>
+		  Traditionally, the first example should welcome the world.
+		  Most of the code handles the frame for integrating a menu
+		  item into Thuban while the actual raising of a message
+		  is done in a single line.
+		  </para>
+			<programlisting>
+			<![CDATA[
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Extend Thuban with a sample Hello World to demonstrate simple
+extensions.
+"""
+
+__version__ = '$Revision: 2627 $'
+
+# use _() already now for all strings that may later be translated
+from Thuban import _
+
+# Thuban has named commands which can be registered in the central
+# instance registry.
+from Thuban.UI.command import registry, Command
+
+# The instance of the main menu of the Thuban application
+# See Thuban/UI/menu.py for the API of the Menu class
+from Thuban.UI.mainwindow import main_menu
+
+def hello_world_dialog(context):
+    """Just raise a simple dialog to greet the world.
+
+    context -- The Thuban context.
+    """
+    context.mainwindow.RunMessageBox(_('Hello World'), _('Hello World!'))
+
+
+# create a new command and register it
+registry.Add(Command('hello_world', _('Hello World'), hello_world_dialog,
+                     helptext = _('Welcome everyone on this planet')))
+
+# find the extensions menu (create it anew if not found)
+extensions_menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))
+
+# finally bind the new command with an entry in the extensions menu
+extensions_menu.InsertItem('hello_world')
+			]]>
+			</programlisting>
+		</section>
+		<section><title>Registering a Command</title>
+		  <para>
+		  Mainly, our new function has to be registered to the Thuban
+		  framework in order to connect it to the menu. A registered
+		  command can also be connected to e.g. a toolbar button.
+		  </para>
+		  <para>
+		  The instances and classes for this are imported at the beginning.
+		  Any code not inside a method or class is directly executed when
+		  the source-code module is imported. Therefore, the second
+		  part of this example consist of the plain statements to create a new
+		  Command and to add it to the menu.
+		  </para>
+		  <para>
+		  By convention, it looks for a menu registered as ``extensions'' to
+		  insert the new command. If it does not exist yet, it gets created.
+		  It is advisable to copy this code for any of your extensions.
+		  </para>
+		</section>
+		<section><title>The Thuban context</title>
+			<para>
+			A registered command that is called, always receives the
+			Thuban context. This instance provides our method with
+			hook references to all important components of the Thuban
+			application.
+			</para>
+			<para>
+	        In the example hello_world.py, our function uses the
+			mainwindow component which offers a method to raise a
+			message dialog. In total there are three hooks:
+			<itemizedlist>
+			<listitem>
+			<para>application:
+			This object is the instance of the Thuban Application class.
+			Except maybe for loading or savinf sessions, you will not
+			need this object for a simple extension.
+			See Thuban/UI/application.py for the API.
+			</para>
+			</listitem>
+			<listitem>
+			<para>session:
+			The instance of the current session. It manages the sessions'
+			map and tables. You can set and remove the map or tables.
+			In may also get the map object. However, you should know that
+			internally it is already prepared to handle many maps.
+			Therfore, currently you would always receive a list with exactlty
+			one element. In the future, if there are more than one map,
+			you will not know which one is the currently display one and
+			therefore you should use the mainwindow as hook to find
+			the currently displayed map.
+			See Thuban/Model/session.py for the API.
+			</para>
+			</listitem>
+			<listitem>
+			<para>
+			mainwindow: The mainwindow object is central to manage various
+			GUI things such as the Legend sub-window. Most notably,
+			you get access to the canvas which is the window part where
+			the map is drawn. The canvas knows, which map it currently
+			draws and therefore you get the current map via
+			context.mainwindow.canvas.Map().
+			See Thuban/UI/mainwindow.py for the API.
+			</para>
+			</listitem>
+			</itemizedlist>
+            </para>
+		</section>
+	</section>
+  </chapter>
+
+  <chapter><title>Trouble Shooting</title>
+    <para>
+    Here are a few problems that users have encountered when first using Thuban.
+    </para>
+    <para>
+
+    <itemizedlist>
+    <listitem>
+    <para>After adding two or more layers nothing is drawn in the map window.
+    </para>
+    <para>
+    This is probably because the layers have different projections. Projections
+    must be set on all layers and on the map itself if the layers' projections
+    are different.
+    </para>
+    </listitem>
+
+    <listitem>
+    <para>Thuban crashes on startup with the error 
+        <literal>NameError: global name 'False' is not defined</literal>.
+    </para>
+    <para>
+    <varname>True</varname> and <varname>False</varname> were only introduced
+    in Python 2.2.1. Thuban depends on at least Python 2.2.1.
+    </para>
+    </listitem>
+
+    <listitem>
+    <para>After compiling Thuban, Thuban crashes with an error similar to
+        <literal>
+        ImportError: /usr/local//lib/thuban/Thuban/../Lib/wxproj.so: undefined symbol: __gxx_personality_v0
+        </literal>
+    </para>
+    <para>
+    Thuban depends on the wxWindows library. If Thuban is compiled with an
+    incompatible version of the compiler than wxWindows was compiled with
+    this error may occur. Try compiling with a different version of the 
+    compiler.
+    </para>
+    </listitem>
+    </itemizedlist>
+    </para>
+    <para>
+    If an error occurs Thuban will display a dialog indicating the error
+    before closing. The text should be copied and reported to the 
+    <ulink url="http://thuban.intevation.org/bugtracker.html">
+    Intevation bugtracker
+    </ulink>.
+    More information about the system is available from 
+    <menuchoice><guimenu>Help</guimenu><guimenuitem>About</guimenuitem></menuchoice> box.
+    This should also be included in the bug report.
+    <figure>
+    <title>Error Dialog</title>
+    <mediaobject>
+    <imageobject><imagedata fileref="../images/8_int_error.png" format="PNG" scale="&imgscale;"/></imageobject>
+    <imageobject><imagedata fileref="./images/8_int_error.eps" format="EPS" scale="&imgscale;"/></imageobject>
+    </mediaobject>
+    </figure>
+    </para>
+
+  </chapter>
+
+  <appendix><title>Supported Data Sources</title>
+    <para>
+    </para>
+    <variablelist>
+    <varlistentry>
+    <term>Shapefile</term>
+    <listitem>
+        <para>
+        The Shapefile format has become a standard format for saving
+        geographic vector information. It supports polygons, lines, and
+        points. 
+        
+        <ulink url="http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf">
+        Technical Specification.
+        </ulink>  
+        </para>
+    </listitem>
+    </varlistentry>
+
+    <varlistentry>
+    <term>dBase file</term>
+    <listitem>
+        <para>
+        dBase files are used to store the attributes for each layer. This
+        is closely associated with the Shapefile format. For detailed 
+        specifications on the correct format of a dBase file used with
+        Thuban please see the Technical Specification for the Shapefile
+        format above.
+        </para>
+    </listitem>
+    </varlistentry>
+
+    <varlistentry>
+    <term>PostGIS</term>
+    <listitem>
+        <para>
+        PostGIS adds support for geographic objects to the PostgreSQL 
+	object-relational database. Different layer types (as for Shapefiles)
+	are supported. <ulink url="http://postgis.refractions.net">PostGIS
+	Homepage</ulink>
+        </para>
+    </listitem>
+    </varlistentry>
+
+    <varlistentry>
+    <term>Raster files</term>
+    <listitem>
+        <para>
+	Binding the GDAL library Thuban supports numerous raster file formats,
+	see <ulink url="http://www.remotesensing.org/gdal/formats_list.html">
+	GDAL format list</ulink> for details.</para>
+
+	<para>Most commonly used is the <emphasis>TIFF/GeoTIFF</emphasis>
+	format: Raster maps are provided as TIFF images, with an additional 
+	"world file" storing the geographic reference (usually with an
+	extension ".tfw").
+        </para>
+    </listitem>
+    </varlistentry>
+
+    </variablelist>
+  </appendix>
+
+  <appendix><title>Working with PostGIS</title>
+  <para>
+  This section focusses on the use of PostGIS in the Thuban framework. For
+  installation and maintenance of spatial databases we refer to the  
+  <ulink url="http://postgis.refractions.net">PostGIS Homepage</ulink>.
+  The Thuban PostGIS support requires the 
+  <ulink url="http://initd.org/software/psycopg">psycopg module</ulink>.
+  </para>
+
+  <para>
+	Working with PostGIS Databases is seperated into two steps:
+	<itemizedlist>
+	<listitem><para>Opening a Database Connection</para></listitem>
+	<listitem><para>Loading a Data Layer</para></listitem>
+	</itemizedlist>
+  </para>
+	<section><title>Opening a Database Connection</title>
+	<para>
+		Before a data layer can be loaded from a PostGIS database a
+		connection with the database has to be established. 
+		<menuchoice>
+        	<guimenu>Session</guimenu>
+        	<guimenuitem>Database Connections ...</guimenuitem>
+        	</menuchoice> opens a dialog for database connection
+		management. In the dialog new connections can be added 
+		and existing ones can be removed. Removing a database
+		connection is not possible if the map still displays a
+		layer provided by this database connection. 
+	</para>
+    <figure>
+    <title>Database Management Dialog</title>
+    <mediaobject>
+    <imageobject><imagedata fileref="../images/app_postgis_db_management.png" format="PNG" scale="&imgscale;"/></imageobject>
+    <imageobject><imagedata fileref="./images/app_postgis_db_management.eps" format="EPS" scale="&imgscale;"/></imageobject>
+    </mediaobject>
+    </figure>
+
+	<para>
+		To add a new database connection to the session a dialog is
+		opened to specify the relevant connection data. Enter all 
+		data relevant for your connection. If the connection fails 
+		the dialog remains open and provides some hints on the failure.
+	</para>
+        <figure>
+    	<title>Add Database Dialog</title>
+    	<mediaobject>
+    	<imageobject><imagedata fileref="../images/app_postgis_db_add.png" format="PNG" scale="&imgscale;"/></imageobject>
+    	<imageobject><imagedata fileref="./images/app_postgis_db_add.eps" format="EPS" scale="&imgscale;"/></imageobject>
+    	</mediaobject>
+    	</figure>
+	
+	<para>
+	It is important to note that information on database connections are
+	also stored with the session. Passwords are NOT stored. If you load a 
+	session with database connections you are asked to enter these
+	passwords again where required.
+	</para>
+
+	</section>
+
+	<section><title>Loading a Data Layer</title>
+	<para>
+	Data layers as part of a map are loaded with the 
+	<menuchoice>
+        <guimenu>Map</guimenu>
+        <guimenuitem>Add Database Layer ...</guimenuitem>
+        </menuchoice> menu item. A dialog is raised displaying two choice
+	lists. In the left list all connected databases are shown.
+	Highlighting
+	one of these and issuing a retrieval results in a list of available 
+	layer tables from that database. After selection of a 
+	layer the dialog is closed.
+	</para>
+        <figure>
+    	<title>Add Database Dialog</title>
+    	<mediaobject>
+    	<imageobject><imagedata fileref="../images/app_postgis_add_layer.png" format="PNG" scale="&imgscale;"/></imageobject>
+    	<imageobject><imagedata fileref="./images/app_postgis_add_layer.eps" format="EPS" scale="&imgscale;"/></imageobject>
+    	</mediaobject>
+    	</figure>
+	
+	</section>
+
+  </appendix>
+
+  <appendix><title>Supported Projections</title>
+    <para>
+    The following types of projections are directly support by 
+    Thuban. The specific values for each are provided by the user
+    to create custom projections. Thuban comes with predefined
+    projections which are available through the Projections dialog.
+    </para>
+    <itemizedlist>
+    <listitem>
+    	<para>Geographic</para>
+	<itemizedlist>
+    	<listitem><para><literal>Ellipsoid</literal></para></listitem>
+    	<listitem><para>
+		<literal>Source Data</literal>: either Degrees or Radians
+		</para></listitem>
+    	</itemizedlist>
+    </listitem>
+    <listitem>
+    	<para>Lambert Conic Conformal</para>
+    <itemizedlist>
+    	<listitem><para><literal>Ellipsoid</literal></para></listitem>
+    	<listitem><para><literal>Latitude of 1st standard parallel</literal></para></listitem>
+    	<listitem><para><literal>Latitude of 2nd standard parallel</literal></para></listitem>
+    	<listitem><para><literal>Central Meridian</literal></para></listitem>
+    	<listitem><para><literal>Latitude of Origin</literal></para></listitem>
+    	<listitem><para><literal>False Easting</literal> (meters)</para></listitem>
+    	<listitem><para><literal>False Northing</literal> (meters)</para></listitem>
+    </itemizedlist>
+    </listitem>
+    <listitem>
+    	<para>Transverse Mercator</para>
+    <itemizedlist>
+    	<listitem><para><literal>Ellipsoid</literal></para></listitem>
+    	<listitem><para><literal>Latitude</literal>of origin</para></listitem>
+    	<listitem><para><literal>Longitude</literal>at central meridian</para></listitem>
+    	<listitem><para><literal>Scale Factor</literal>at central meridian</para></listitem>
+    	<listitem><para><literal>False Easting</literal> (meters)</para></listitem>
+    	<listitem><para><literal>False Northing</literal> (meters)</para></listitem>
+    </itemizedlist>
+    </listitem>
+    <listitem>
+    	<para>Universal Transverse Mercator</para>
+    <itemizedlist>
+    	<listitem><para><literal>Ellipsoid</literal></para></listitem>
+    	<listitem><para><literal>Zone</literal> 
+		(can be guessed appling the Propose button)</para></listitem>
+    	<listitem><para><literal>Southern Hemisphere</literal> flag</para></listitem>
+    </itemizedlist>
+    </listitem>
+    </itemizedlist>
+    
+    <para>
+    Thuban comes with a sample set of map projections for various 
+    European countries. Apart from the basic projection they differ 
+    especially in their parameterization:
+    </para>
+    <itemizedlist>
+    <listitem><para>Belgium Datum 1972 (Lambert Conic Conformal)</para>
+    </listitem>
+ 
+    <listitem><para>Gauss-Boaga Zone 1 (Italy, Transverse Mercartor)</para>
+    </listitem>
+ 
+    <listitem><para>Gauss-Krueger Zone 2 (Germany, Transverse Mercartor)
+    </para>
+    </listitem>
+ 
+    <listitem><para>Reseau Geodesique Francaise 
+    (France, Lambert Conic Conformal)</para>
+    </listitem>
+ 
+    <listitem><para>UK National Grid (United Kingdom, Transverse Mercartor)
+    </para>
+    </listitem>
+    </itemizedlist>
+
+    <para>
+    Thuban uses the comprehensive PROJ library for projections. PROJ provides
+    more than the four commonly used projections described above. If needed
+    Thuban can be easily extended to a new projection covered by PROJ.
+    </para>
+  </appendix>
+
+</book>
+

Added: packages/thuban/branches/upstream/current/Doc/manual/thuban-manual.xml
===================================================================
--- packages/thuban/branches/upstream/current/Doc/manual/thuban-manual.xml	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/manual/thuban-manual.xml	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1997 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book
+	PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+    [<!ENTITY imgscale "60">]>
+<!-- $Revision: 2727 $ -->
+<book>
+  <bookinfo>
+    <title>User's Manual for Thuban 1.2 (Draft)</title>
+	<authorgroup>
+      <author>
+        <firstname>Jonathan</firstname><surname>Coles</surname>
+      </author>
+      <author>
+        <firstname>Jan-Oliver</firstname><surname>Wagner</surname>
+      </author>
+      <author>
+        <firstname>Frank</firstname><surname>Koormann</surname>
+      </author>
+	</authorgroup>
+    <copyright>
+      <year>2003, 2004, 2005, 2006, 2007</year>
+      <holder>Intevation GmbH</holder>
+    </copyright>
+   <revhistory>
+<!-- comment this first revision out when releasing a real version -->
+<!--
+     <revision>
+        <revnumber>SVN version $Id: thuban-manual.xml 2727 2007-02-20 10:44:51Z bernhard $</revnumber>
+        <date></date>
+        <revremark>Under development.</revremark>
+     </revision>
+-->
+     <revision>
+        <revnumber>1.2.0</revnumber>
+        <date>20-Feb-2007</date>
+        <revremark>
+			Removed all installation instructions in favor
+			of a link to the website. It is not wise to
+			double the README contents here.
+		</revremark>
+     </revision>
+     <revision>
+        <revnumber>1.0.0</revnumber>
+        <date>22-Jan-2004</date>
+        <revremark>
+			Corresponds to Thuban 1.0.0.
+			New: Installation instructions for Win32.
+		</revremark>
+     </revision>
+     <revision>
+        <revnumber>1.0pre3</revnumber>
+        <date>04-Dec-2003</date>
+        <revremark>
+			Corresponds to Thuban 1.0rc1.
+			New: I18n, right button legend menu, EPSG projectons,
+            PostGIS support.
+		</revremark>
+     </revision>
+     <revision>
+        <revnumber>1.0pre2</revnumber>
+        <date>29-Aug-2003</date>
+        <revremark>
+			Corresponds to Thuban development release 0.8.1.
+			New: chapter on extensions.
+		</revremark>
+     </revision>
+     <revision>
+        <revnumber>1.0pre1</revnumber>
+        <date>08-Aug-2003</date>
+        <revremark>Corresponds to Thuban development release 0.8.1.</revremark>
+     </revision>
+  </revhistory>
+
+  </bookinfo>
+
+  <chapter><title>Introduction</title>
+    <para>
+    Thuban is an interactive geographic data viewer.
+    Its development had been started because there was no simple interactive
+    viewer for geographic information available as Free Software. Thuban is 
+    written mainly in Python and uses the wxWidgets (former wxWindows)
+    library allowing it to 
+    run on many different platforms, including GNU/Linux and Windows.
+    </para>
+    <para>
+    Geographic data viewers are a necessary tool as they allow one to
+	get a visual 
+    impression of the positional relationship of the information that may not
+    be apparent from simple inspection of the data values themselves. 
+    Thuban allows the user to create a session that displays
+    geographic data and then explore that data through navigation and
+    manipulation of how it is drawn. The results can then be saved or printed.
+    </para>
+    <para>
+    Thuban arranges a session in a hierarchy. A session contains a map which
+    consists of layers. Each layer represents a data set. For 
+    instance, there may be a layer for roads and another layer for buildings. 
+    These layers can either be vector shapes or images.
+    </para>
+
+  	<section><title>Installation</title>
+        <para>
+        Thuban is actively supported under Debian 4.0 (Etch)
+	and Windows (XP). Of course it is possible to run Thuban
+	on a variety of other platforms.
+
+	Please check <ulink url="http://thuban.intevation.org/">
+        Thuban's Website
+        </ulink> about how to install Thuban and the lastest information
+	about the supported platforms.
+	</para>
+  	</section>
+
+	<section><title>Internationalization</title>
+        <para>
+	Thuban is implemented with internationalization support. So far Thuban
+	is translated by volunteers to the following languages (apart from its
+	main language: English):
+	<itemizedlist>
+            <listitem><para>French</para></listitem>
+            <listitem><para>German</para></listitem>
+            <listitem><para>Italian</para></listitem>
+		<listitem><para>Portuguese (Brazilian)</para></listitem>
+            <listitem><para>Russian</para></listitem>
+            <listitem><para>Spanish</para></listitem>
+	</itemizedlist>
+	</para>
+
+	<para>
+	To use internationalization under POSIX systems (like GNU/Linux)
+	you have to set the environment variable LC_ALL accordingly (e.g.
+	LC_ALL=fr_FR for the french language support). Please check your 
+	systems documentation for details and supported settings.
+	Specifiying LC_ALL on the command line while launching thuban 
+	allows appication specific language settings:
+	</para>
+	<programlisting>
+	LC_ALL=fr_FR thuban.py
+	</programlisting>
+
+	<para>
+	MS Windows users have to specify the language to be used via the control
+	bar (which effects all applications).
+	</para>
+	</section>
+
+  	<section><title>The Main Window</title>
+    	<para>
+	<figure>
+	<title>The Main Window</title>
+        <mediaobject>
+        <imageobject> <imagedata fileref="../images/1_2_mainwindow.png" format="PNG" scale="&imgscale;"/> </imageobject>
+        <imageobject> <imagedata fileref="./images/1_2_mainwindow.ps" format="EPS" scale="&imgscale;"/> </imageobject>
+        </mediaobject>
+	</figure>
+        </para>
+
+        <para>
+        The map window shows the current state of the map and is where
+        the user can interact with the map using the tools. 
+        </para>
+
+        <para>
+        The legend on the left displays a list of the current layers and 
+        any visible classification groups. In the example, each shape layer 
+        has a default classification which specifies how the shapes in each 
+        layer are drawn. Layers that are higher in the list appear 
+        ``closer'' to the user. The legend can be closed by clicking on the 
+        small X in the upper right-hand region of the legend. 
+        To open it again, use
+        <menuchoice>
+        <guimenu>Map</guimenu>
+        <guimenuitem>Legend</guimenuitem>
+        </menuchoice>.
+        The legend is also dockable, which means that it can be detached 
+        from the main window by clicking on the small button next to the 
+        close button. It can be attached by clicking the same button
+        again.
+        </para>
+        <para>
+        The status bar displays different information depending on the
+        current context. If the user is selecting an item from the menu
+        then the status bar will display a short help message indicating
+        what each menu item is for. If the user has a tool selected then
+        the position of the cursor on the map is displayed.
+        </para>
+        <para>
+        The tool bar provides quick access to the commonly needed tools.
+        By hovering over each button the user can see a short messages
+        describing what the tool does. The tools provided are Zoom In, Zoom
+        Out, Pan, Full Extent, Full Layer Extent, Full Shape Extent, Identify,
+        and Label. Each of the tools will be explained in further detail later
+        in the manual.
+        </para>
+  	</section>
+
+  </chapter>
+
+  <chapter><title>Session Management</title>
+
+  	<section><title>Starting a New Session</title>
+    	<para>
+        A new session can be started from 
+        <menuchoice>
+        <guimenu>File</guimenu>
+        <guimenuitem>New Session</guimenuitem>
+        </menuchoice>. 
+        If a session is already loaded and has been modified without
+        being saved a prompt will ask if the current session should
+        be saved. A new session consists of an empty map with no
+        layers, no tables and no projection.
+    	</para>
+  	</section>
+
+  	<section><title>Opening a Session</title>
+    	<para>
+        A session can be opened from 
+        <menuchoice>
+        <guimenu>File</guimenu>
+        <guimenuitem>Open Session</guimenuitem>
+        </menuchoice>. A dialog box will open allowing the user to browse
+        for a Thuban Session file. Thuban session files end with
+        <varname>.thuban</varname>. Selecting a file a clicking
+        <guibutton>OK</guibutton> will load the session into Thuban.
+		</para>
+
+		<para>
+        If a session is already loaded and has been modified without
+        being saved a prompt will ask if the current session should
+        be saved.
+    	</para>
+		
+		<para>
+		Thuban provides a path recovery feature: If a (shape) file referenced
+		in a Thuban session cannot be found at the specified location, the user 
+		is prompted a file dialog. Here a new location can be selected for the 
+		currents layer data source. Cancelling the dialog removes the layer
+		from the session. If a new location has been selected, Thuban checks
+		this again, if further layers data sources are missing. The user is
+		informed about this and can accept or cancel the suggestion.
+    	</para>
+  	</section>
+
+  	<section><title>Saving a Session</title>
+    	<para>
+        A session can be saved from 
+        <menuchoice>
+        <guimenu>File</guimenu>
+        <guimenuitem>Save Session</guimenuitem>
+        </menuchoice>.
+		In the case the session is not a new and unsaved one,
+		the corresponding file is updated with the current session
+		data.
+		In the case the current session is a new one and yet unsaved
+		a dialog box will open allowing the user to browse
+        the file system and select a place to save the session. Thuban
+        sessions should be saved under a name ending in 
+        <varname>.thuban</varname>. If the file already exists the user
+        will be prompted to save under a different name or overwrite the
+        existing file.
+    	</para>
+  	</section>
+
+  	<section><title>The Session Info-Tree</title>
+        <para>
+        <figure>
+        <title>Session Info Tree</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/2_4_session_tree.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/2_4_session_tree.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+    	<para>
+        The session info-tree is primarily intended for developers working
+        with Thuban. It displays many of the internal values for the session,
+        map, and layers. It can be opened from
+        <menuchoice>
+        <guimenu>File</guimenu>
+        <guimenuitem>Session Tree</guimenuitem>
+        </menuchoice>. 
+    	</para>
+  	</section>
+  </chapter>
+
+  <chapter><title>Map Management</title>
+    <para>
+    The map consists of a number of layers where each layer represents a
+    different type of data set. By interacting with the map the user can
+    visually explore the data. 
+    </para>
+    <para>
+    The map can have a name that will appear in the Thuban title bar. 
+    The map name can be changed using 
+    <menuchoice>
+    <guimenu>Map</guimenu>
+    <guimenuitem>Rename</guimenuitem>
+    </menuchoice>.
+    </para>
+    <para>
+    <inlinemediaobject>
+    <imageobject> 
+    <imagedata fileref="../images/3_rename_map.png" format="PNG" scale="&imgscale;"/> 
+    </imageobject> 
+    <imageobject> 
+    <imagedata fileref="./images/3_rename_map.eps" format="EPS" scale="&imgscale;"/> 
+    </imageobject>
+    <textobject> <phrase>Rename Map</phrase> </textobject>
+    </inlinemediaobject>
+    </para>
+
+  	<section><title>Adding and Removing Layers</title>
+    	<para>
+        There are three types of layers that can be added to a map: 
+	Shape layers, database layers
+        and image layers. Shape layers are stored in Shapefile format, a
+        widely used file format for storing geographic objects. These
+        files have the extension ``.shp''. Associated with
+        the shape file is a database file which stores attributes for
+        each shape in the Shape file. This file, in dBase format, 
+        has the extension ``.dbf''. Both files must have the same base name.
+        For example, if there is a shape file named roads.shp there must
+        also be a file roads.dbf.
+    	</para>
+	<itemizedlist>
+	<listitem>
+	<para>
+        Shape layers can be added to the map with
+        <menuchoice>
+        <guimenu>Map</guimenu>
+        <guimenuitem>Add Layer</guimenuitem>
+        </menuchoice>.
+        Initially, only the ``.shp'' files are shown which is enough for the
+		selection. However, if you switch to display all files and select one
+		of the associated files (e.g. ``.dbf''), Thuban will recognize the base
+		name and load the corresponding Shape file.
+    	</para>
+		<para>
+		The file dialog for Shape files allows to select multiple files.
+		Use the shift-button together with the left mouse button to extend
+		the selection.
+    	</para>
+	</listitem>
+
+	<listitem>
+    	<para>Database layers can be added to the map with 
+	<menuchoice>
+        <guimenu>Map</guimenu>
+        <guimenuitem>Add Database Layer</guimenuitem>
+        </menuchoice>.
+	A dialog with two lists is opened. The left list displays all 
+	database connections currently open for the session. You can retrieve 
+	a list of available layers from the selected database which is
+	displayed on the right hand. From this list one layer can be selected,
+	the dialog is closed afterwards. 
+    	</para>
+	<para>
+	See appendix ``Working with PostGIS'' for details.
+	</para>
+	</listitem>
+
+	<listitem>
+    	<para>
+        Image layers can be added to the map with
+        <menuchoice>
+        <guimenu>Map</guimenu>
+        <guimenuitem>Add Image Layer</guimenuitem>
+        </menuchoice>.
+        It is important to select a valid image file that has geographic
+        data associated with it. The data can be embedded in the file itself, 
+        or in another file. If geographic information cannot be found, Thuban 
+        will report an error.
+    	</para>
+	</listitem>
+	</itemizedlist>
+  	</section>
+
+  	<section><title>Navigation</title>
+    	<para>
+        The map can be explored by using the navigation tools available on 
+        the tool bar or from the 
+        <menuchoice><guimenu>Map</guimenu></menuchoice> menu. 
+    	</para>
+	<itemizedlist>
+	<listitem>
+    	<para>
+        The ZoomIn tool 
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_zoomin.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_zoomin.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>ZoomIn Tool</phrase> </textobject>
+        </inlinemediaobject>
+        enlarges a region of the map. Clicking once on the map
+        will double the magnification and center the map on the point that
+        was clicked. Clicking and dragging selects a region that will be
+        enlarged to fit the window.
+    	</para>
+	</listitem>
+	<listitem>
+    	<para>
+        The ZoomOut tool 
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_zoomout.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_zoomout.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>ZoomOut Tool</phrase> </textobject>
+        </inlinemediaobject>
+        shrinks the map so that a larger region is visible. A single click
+        reduces the magnification by a factor of two. Clicking and dragging
+        selects a box such that the current contents of the window will be
+        scaled to fit into that box.
+    	</para>
+	</listitem>
+	<listitem>
+    	<para>
+        The Pan tool 
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_pan.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_pan.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Pan Tool</phrase> </textobject>
+        </inlinemediaobject>
+        allows the user to move the map around by clicking and dragging.
+    	</para>
+	</listitem>
+	<listitem>
+    	<para>
+        The Full Extent tool 
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_fullextent.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_fullextent.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Full Extent Tool</phrase> </textobject>
+        </inlinemediaobject>
+        rescales the viewable region so that the entire map is visible.
+    	</para>
+	</listitem>
+	<listitem>
+    	<para>
+        The Full Layer Extent tool 
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_fulllayerextent.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_fulllayerextent.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Full Layer Extent Tool</phrase> </textobject>
+        </inlinemediaobject>
+        rescales the viewable region so that the currently selected
+        layer fits within the window. If no layer is selected this button 
+        will be disabled.
+    	</para>
+	</listitem>
+	<listitem>
+    	<para>
+        The Full Shape Extent tool 
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_2_fullshapeextent.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_2_fullshapeextent.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Full Shape Extent Tool</phrase> </textobject>
+        </inlinemediaobject>
+        rescales the viewable region so that the currently selected
+        shape fits within the window. If the shape is a point, it is
+        centered and the map is zoomed all the way in. If no shape is 
+        selected this button will be disabled. This feature is especially
+        helpful when identifying an object related to a selected record 
+        in a tableview (see below).
+
+    	</para>
+	</listitem>
+	</itemizedlist>
+  	</section>
+
+  	<section><title>Object Identification</title>
+    	<para>
+        Objects on the map can be identified using the Identify tool
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_3_identify.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_3_identify.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Identify Tool</phrase> </textobject>
+        </inlinemediaobject>.
+        Clicking on an object selects that object and opens a dialog which 
+        shows all the table attributes for that object. Any current selection
+        is lost. Objects on the map are typically shapes and this document
+        will often refer to objects as shapes.
+    	</para>
+  	</section>
+
+  	<section><title>Object Labeling</title>
+    	<para>
+        Objects can be labeled using the Label tool
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_3_label.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_3_label.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Label Tool</phrase> </textobject>
+        </inlinemediaobject>.
+        Clicking on an object selects that object and opens a dialog which
+        displays the table attributes for that object. An attribute can
+        be selected to be the label on the map. The label will be placed
+        at the center of the shape. Clicking on an object that already has 
+        a label will remove the label.
+    	</para>
+  	</section>
+
+  	<section><title>The Legend</title>
+        <para>
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_legend.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_legend.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Legend</phrase> </textobject>
+        </inlinemediaobject>
+        </para>
+    	<para>
+        The Legend provides an overview of the layers in the map. Layers
+        that appear higher in the legend will appear ``closer'' to the user.
+        If a layer supports classification (currently, only shape layers 
+        have this feature) then the classification groups will be shown
+        below each layer. The properties for each group are also displayed
+        with a small graphic. Polygon layers appear as rectangles, lines
+        appear as curved lines, and points appear as circles. 
+        </para>
+        <para>
+        Along the top of the legend is a toolbar which allows quick access
+        to some of the layer manipulation options under
+        <menuchoice><guimenu>Map</guimenu></menuchoice>. 
+        </para>
+
+	<itemizedlist>
+	<listitem>
+        <para>
+        The Move Layer to Top tool
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_totop.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_totop.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Move Layer to Top</phrase> </textobject>
+        </inlinemediaobject> raises the selected layer to the top of the map.
+        </para>
+	</listitem>
+	<listitem>
+
+        <para>
+        The Move Layer Up tool
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_moveup.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_moveup.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Move Layer Up</phrase> </textobject>
+        </inlinemediaobject> raises the selected layer one level.
+        </para>
+	</listitem>
+	<listitem>
+
+        <para>
+        The Move Layer Down tool
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_movedown.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_movedown.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Move Layer Down</phrase> </textobject>
+        </inlinemediaobject> lowers the selected layer one level.
+        </para>
+
+	</listitem>
+	<listitem>
+        <para>
+        The Move Layer to Bottom tool
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_tobottom.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_tobottom.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Move Layer to Bottom</phrase> </textobject>
+        </inlinemediaobject> lowers the selected layer to the bottom of the map.
+        </para>
+
+	</listitem>
+	<listitem>
+        <para>
+        The Visible tool
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_visible.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_visible.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Visible</phrase> </textobject>
+        </inlinemediaobject> shows the selected layer in the map if it was
+        hidden.
+        </para>
+
+	</listitem>
+	<listitem>
+        <para>
+        The Invisible tool
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_invisible.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_invisible.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Invisible</phrase> </textobject>
+        </inlinemediaobject> hides the selected layer in the map.
+        </para>
+
+	</listitem>
+	<listitem>
+        <para>
+        The Properties tool
+        <inlinemediaobject>
+        <imageobject> 
+        <imagedata fileref="../images/3_5_props.png" format="PNG" scale="&imgscale;"/> 
+        </imageobject> 
+        <imageobject> 
+        <imagedata fileref="./images/3_5_props.eps" format="EPS" scale="&imgscale;"/> 
+        </imageobject>
+        <textobject> <phrase>Properties</phrase> </textobject>
+        </inlinemediaobject> opens the layer's properties dialog box.
+        Double-clicking on a layer or a group of a layer will open the 
+        properties dialog for that layer.
+    	</para>
+	</listitem>
+	</itemizedlist>
+
+	<para>
+	The most used layer related actions are also available from a 
+	popup menu. It is raised when a layer is clicked with the right mouse
+	button.
+	</para>
+	
+	<para>
+        <figure>
+        <title>Layer Popup Menu</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/3_5_popup_menu.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/3_5_popup_menu.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+
+        <para>
+        Along the bottom of the legend is the scalebar. The scalebar
+        will be available if there are any layers and the  map has a 
+        projection set.
+        </para>
+  	</section>
+
+  	<section><title>Exporting</title>
+        <para>
+        Under Windows, maps can be exported in Enhanced Metafile format
+        (<varname>.wmf</varname>)
+        from 
+        <menuchoice>
+        <guimenu>Map</guimenu>
+        <guimenuitem>Export</guimenuitem>
+        </menuchoice> for use in reports, presentations, or further 
+        modification. The current map view, legend, and, if available,
+        scalebar are exported. Under other platforms this option is not 
+        available. Clicking this menu item open a file selection dialog 
+        that lets the user select a location to export the map. 
+        </para>
+  	</section>
+
+  	<section><title>Printing</title>
+    	<para>
+        The map can be printed using 
+        <menuchoice>
+        <guimenu>Map</guimenu>
+        <guimenuitem>Print</guimenuitem>
+        </menuchoice>. The current map view, legend, and, if available,
+        scalebar are printed. A standard printing dialog will open allowing 
+        the user to configure the printer. This dialog will differ depending
+        on which platform Thuban is running.
+    	</para>
+  	</section>
+
+  </chapter>
+
+  <chapter><title>Layer Management</title>
+    <para>
+    </para>
+
+  	<section><title>Types of Layers</title>
+    	<para>
+        There are three types of layers supported by Thuban: shape layers,
+	database layers and
+        image layers. Shape layers consist of vector based shapes with 
+        geo-referenced coordinates. There are three types of supported 
+        shapes: polygons, lines (arc), and points. Database layers are similar
+	to shape layers but loaded from a database instead of the file system.
+	Image layers can be any image
+        file format supported by the Geo-spatial Data Abstraction Library
+        (GDAL). The images must have geographic
+        coordinate data either embedded within the file or in a separate
+        file that is in the same directory as the image file. GeoTIFF files 
+        work very well with Thuban and were designed specifically to be image 
+        layers in GIS programs.
+    	</para>
+        <para>
+        All actions in the
+        <menuchoice>
+        <guimenu>Layer</guimenu>
+        </menuchoice> menu act on the currently selected layer in the legend.
+        </para>
+  	</section>
+
+  	<section><title>Properties</title>
+    	<para>
+        To view the properties for a layer it must first be selected in the
+        legend. The menu option
+        <menuchoice>
+        <guimenu>Layer</guimenu>
+        <guimenuitem>Properties</guimenuitem>
+        </menuchoice> opens a dialog that displays a layer's properties.
+        All layers have a title which can be modified in the text field
+        provided. The type of layer is also shows. If the type is a type
+        of shape (polygon, arc, point) the classification table will be
+        shown. Image layers have no other properties other than title 
+        and type.
+    	</para>
+        <para>
+        <figure>
+        <title>Properties Window</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/4_2_layer_properties.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/4_2_layer_properties.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+    	</para>
+        <para>
+        <figure>
+        <title>Properties Window</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/4_2_raster_layer_properties.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/4_2_raster_layer_properties.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+    	</para>
+  	</section>
+
+  	<section><title>Visibility</title>
+    	<para>
+        Sometimes it is not desirable to view all layers at the same time.
+        Some layers may take a long time to draw and so while navigating
+        around the map the user may not want to wait for the map to redraw
+        all the layers each time the map is changed. Each layer can be 
+        independently turned on or off using the 
+        <menuchoice>
+        <guimenu>Layer</guimenu>
+        <guimenuitem>Show</guimenuitem>
+        </menuchoice>
+        or
+        <menuchoice>
+        <guimenu>Layer</guimenu>
+        <guimenuitem>Hide</guimenuitem>
+        </menuchoice> options respectively.
+    	</para>
+  	</section>
+
+  	<section><title>Duplication</title>
+    	<para>
+        Layers and all their properties, including classifications, can
+        be duplicated using 
+        <menuchoice>
+        <guimenu>Layer</guimenu>
+        <guimenuitem>Duplicate</guimenuitem>
+        </menuchoice>. Duplicating a layer is useful if the user wishes
+        to model a layer in several different ways. Even though the layers
+        overlap, by carefully selecting the shape properties it is possible
+        to display several pieces of information at once. For example, one
+        copy of a roads layer may be classified on a length property and
+        another copy may be classified on a type property. If the length
+        property was expressed with color and the type property expressed
+        with line thickness then it would be possible to view both
+        classifications by placing the type property copy over the 
+        length property copy.
+    	</para>
+  	</section>
+
+  </chapter>
+
+  <chapter><title>Layer Classifications</title>
+    <para>
+    A layer classification is a way of assigning drawing properties to
+    groups of shapes based on attributes stored in the layer's table. 
+    Only layer's with shapes can have a classification; image layers
+    cannot be classified.
+    </para>
+    <para>
+    A classification consists of a number of groups, each group
+    having a value or range of values to match against, and symbol 
+    properties which control how a shape is drawn on the map. The user
+    selects which field in the table is used by the classification and
+    when the map is drawn the value for that field for each shape is
+    compared with each group's value. The properties of the first group 
+    to match are used to draw the shape. This allows the user to get a 
+    visual impression of not only how the data is laid out but also what 
+    kind of data lies where.
+    </para>
+    <para>
+    A layer always has a classification. When a new layer is added to the
+    map, a default classification is created with the DEFAULT group. This
+    group cannot be removed but can be hidden (see below). Every shape in the 
+    layer, regardless of its attributes, will match this group if no other 
+    group matches. 
+    </para>
+
+  	<section><title>Editing Classifications</title>
+    	<para>
+        A layer's classification can be modified under the properties dialog 
+        (<menuchoice>
+        <guimenu>Layer</guimenu>
+        <guimenuitem>Properties</guimenuitem>
+        </menuchoice>). The layer's classification field can be set to None, 
+        which simply assigns a DEFAULT group to the classification. No new 
+        groups can be added to the classification if the field is None.
+        The user must first select a field to classify on. New groups can
+        be added to the classification with the <guibutton>Add</guibutton>
+        button. 
+        </para>
+        <para>
+        To apply the changes to the map the user can click
+        either <guibutton>Try</guibutton> or <guibutton>OK</guibutton>.
+        <guibutton>Try</guibutton> will not close the dialog box, allowing
+        the user to see how the classification changes the map. 
+        <guibutton>Revert</guibutton> will undo the last classification applied
+        to the map. <guibutton>OK</guibutton> will commit the changes and
+        close the dialog. The user will be unable to undo the changes.
+        <guibutton>Close</guibutton> simply closes the dialog box. If any
+        changes have not been applied with <guibutton>Try</guibutton> the 
+        changes will not be applied to the map.
+        </para>
+        <para>
+        <figure>
+        <title>Properties Window</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_classification.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_classification.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+        <para>
+        The order of the groups in the classification is significant
+        except for the DEFAULT group, which remains at the top. When shapes
+        are matched against groups the matching begins at the first group
+        after the DEFAULT group so that groups higher in the list will 
+        be checked first. Matching for a 
+        given shape will stop at the first group that matches. The user can
+        use <guibutton>Move Up</guibutton> and <guibutton>Move Down</guibutton>
+        to change the order of the groups. The DEFAULT group will always 
+        match a shape that hasn't matched another group.
+    	</para>
+  	    <section><title>Visible</title>
+    	    <para>
+            The Visible column has check-boxes that determine whether a
+            classification group will be displayed in the legend. This is
+            useful if the user knows that the groups completely cover
+            the data set and don't want the DEFAULT group to be displayed
+            in the legend and on a printout.
+            </para>
+        </section>
+  	    <section><title>Symbols</title>
+    	    <para>
+            Each type of shape has its own type of symbol. Thuban supports three
+            types of shapes: polygons, lines, and points. Polygons and points 
+            have outline and fill color, while lines have only line color. Each 
+            group has associated symbol properties. To edit the symbol 
+            properties for a group the user can double click on the Symbol 
+            column or select a group and click the 
+            <guibutton>Edit Symbol</guibutton> button.
+    	    </para>
+  	    </section>
+        <section><title>Value</title>
+            <para>
+            The Value column of the classification table is the value that will
+            be matched when the map is being drawn. The type of filter that can
+            entered into this field depends on the type of data of the 
+            classification field:
+	    </para>
+            <para>
+            If the field is of type Text, anything entered
+            into the field is valid. By default the text will be compared 
+            literally to the
+            value of the shape attribute, including case sensitivity.
+            Alternatively the comparison can be based on regular experessions.
+            Right-click on the row label to open a popup menu with the options
+            <guibutton>Singleton</guibutton> (literal comparison) and  
+            <guibutton>Pattern</guibutton> (regular expressions).  
+            </para>
+            <para> 
+            If the type is Integer, then any valid integer may be entered. In 
+            addition, with special syntax, a range of values can be entered.
+            A range from <varname>start</varname> to <varname>end</varname> 
+            inclusive is specified like this: <literal>[start;end]</literal>.
+            The exclusive range is specified like this: 
+            <literal>]start;end[</literal>. Ranges can include infinity like
+            this: <literal>[-oo;oo]</literal>. Field types can also be of type
+            Decimal. They represent any rational number and can be used in 
+            ranges as well.
+            </para>
+       </section>
+  	    <section><title>Label</title>
+    	    <para>
+            By default, the text that is displayed for a group in the legend
+            is the value for that group. The label can substitute a more
+            descriptive term in the legend.
+            </para>
+        </section>
+  	</section>
+
+  	<section><title>Generating Classes</title>
+    	<para>
+        <figure>
+        <title>Generate Class</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_3_genclass.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_3_genclass.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+    	</para>
+    	<para>
+        Creating a classification by hand can be tedious. 
+        Thuban, therefore, provides a means of generating an entire
+        classification at once while still giving the user control over
+        how it appears. Clicking <guibutton>Generate Class</guibutton>
+        opens the <varname>Generate Classification</varname> dialog.
+        Under the <varname>Generate</varname> pull down there are at most
+        three different ways to generate classifications: 
+        Unique Values, Uniform Distribution, and Quantiles. Some options 
+        may not be available if the data type for the field does not
+        support them. For instance, <varname>Uniform Distribution</varname>
+        doesn't make sense for a Text field.
+    	</para>
+        <para>
+        For every way of generating a classification, a color scheme must
+        be selected. Thuban provides several different color schemes that
+        affect how the group properties change over the classification.
+        It may be desirable that only certain properties change over the
+        classification. If the shape type is a polygon or a point then
+        the <guibutton>Fix Border Color</guibutton> option will be available.
+        This allows the user to select a border color for all classification
+        groups.
+        It is also possible to create a custom color scheme. Selecting
+        this option will display two symbols: the one of the left has the
+        properties of the first group and the one on the right has the 
+        properties of the last group. Thuban will interpolate between these
+        two properties to generate the other groups.
+        <figure>
+        <title>Custom Color Scheme</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_2_custom_ramp.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_2_custom_ramp.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+        <para>
+        The Unique Values option lets the user select specific values that
+        appear in the table. Clicking <guibutton>Retrieve From Table</guibutton>
+        searches the table for all unique values and displays them in the
+        list on the left. Items can be selected and moved to the list on the
+        right. Each list can be sorted or reversed for easier searching.
+        The classification that is generated will be in the same order as
+        the list on the right.
+        <figure>
+        <title>Unique Values</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_2_unique_values.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_2_unique_values.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+        <para>
+        The Uniform Distribution option creates a user specified number of
+        groups of ranges such that each range covers equal intervals. The
+        minimum and maximum values can automatically be retrieved from the
+        table by clicking <guibutton>Retrieve From Table</guibutton>. The
+        stepping is how large each interval is. Adjusting this value will
+        automatically recalculate how many groups is appropriate.
+        <figure>
+        <title>Uniform Distribution</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_2_uniform_dist.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_2_uniform_dist.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+        <para>
+        The Quantiles option generates ranges based on the number of items
+        in the table. For example, by specifying five groups Thuban will
+        generate five groups with appropriate ranges such that 20% of the table
+        data is in each group. If it is impossible to generate exact
+        groupings, Thuban will issue a warning but allow the user to continue.
+        <figure>
+        <title>Quantiles</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/5_2_quantiles.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/5_2_quantiles.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+  	</section>
+  </chapter>
+
+  <chapter><title>Projection Management</title>
+    <para>
+    Projections control how the geographic data is displayed on the screen.
+    If multiple layers are loaded into Thuban where the geographic data
+    is in a different projection system, then the user must specify a
+    projection for each layer. The user must also tell Thuban which
+    projection the map is in. This can be the same as the layers or a different
+    projection in which case the layers are reprojected into that space.
+    The map projection can be set using 
+    <menuchoice>
+    <guimenu>Map</guimenu>
+    <guimenuitem>Projection</guimenuitem>
+    </menuchoice> and the layer projection can be set using 
+    <menuchoice>
+    <guimenu>Layer</guimenu>
+    <guimenuitem>Projection</guimenuitem>
+    </menuchoice>.
+    <figure>
+    <title>Projection Window</title>
+    <mediaobject>
+    <imageobject><imagedata fileref="../images/6_projection.png" format="PNG" scale="&imgscale;"/></imageobject>
+    <imageobject><imagedata fileref="./images/6_projection.eps" format="EPS" scale="&imgscale;"/></imageobject>
+    </mediaobject>
+    </figure>
+    </para>
+    <para>
+    Thuban is distributed with a sample collection of projections and the 
+    set of coordinate systems as used by the EPSG
+    (European Petroleum Survey Group). This quite large set is only displayed
+    if activated by the according checkbox. The set falls into two parts:
+    deprecated lists all projections which are no longer part of the 
+    EPSG data base.
+    </para>
+    <para>
+	 The
+    user can create new projections and make them available to all
+    future Thuban sessions. They may also be exported and imported so
+    that custom projections can be distributed.
+    </para>
+  	<section><title>Selecting a Projection</title>
+        <para>
+        The available projections are listed on the left. If the layer
+        or map already has a projection it will initially be highlighted
+        and will end with <varname>(current)</varname>. Selecting 
+        <varname>&lt;None&gt;</varname> will cause Thuban to use the data as
+        it appears in the source file and will not use a projection.
+        </para>
+    </section>
+  	<section><title>Editing a Projection</title>
+        <para>
+        Whenever a projection is selected from the list its properties
+        are displayed on the right. These properties can be changed
+        and the changes saved to the selected projection using
+        <guibutton>Update</guibutton>. Only a projection that comes
+        from a file can be updated, so if the current layer's projection
+        is selected, <guibutton>Update</guibutton> will be disabled. 
+        <guibutton>Add to List</guibutton> adds the projection to the 
+        list of available projections as a new entry, and thus makes it 
+        available to future Thuban sessions. Clicking <guibutton>New</guibutton>
+        will create an entirely new, empty projection. The 
+        <guibutton>Remove</guibutton> button will permanently remove a 
+        projection from the list of available projections.
+        </para>
+        <para>
+        To apply the selected projection to the map the user can click
+        either <guibutton>Try</guibutton> or <guibutton>OK</guibutton>.
+        <guibutton>Try</guibutton> will not close the dialog box, allowing
+        the user to see how the projeciton changes the map. 
+        <guibutton>Revert</guibutton> will undo the last projection applied
+        to the map. <guibutton>OK</guibutton> will commit the changes and
+        close the dialog. The user will be unable to undo the changes.
+        <guibutton>Close</guibutton> simply closes the dialog box. If no
+        selection has been applied with <guibutton>Try</guibutton> the 
+        selection will not be applied to the map.
+        </para>
+    </section>
+  	<section><title>Importing/Exporting Projections</title>
+        <para>
+        The projections that appear in the list of available projections
+        can be exported to another file that the user chooses. By selecting
+        one or more projections and clicking <guibutton>Export</guibutton>
+        the user will be able to select a file in which to store those 
+        projections.
+        The file can then be distributed to other Thuban users. To import
+        a projection file the user can click <guibutton>Import</guibutton>.
+        The imported projections are added to the list and are then available
+        to the current session and any future Thuban sessions.
+        </para>
+    </section>
+  </chapter>
+
+  <chapter><title>Table Management</title>
+    <para>
+    Thuban distinguishes two different types of tables: Attribute tables
+    (which belong to a layer) and normal data tables. Both provide
+   	the same general functionality with the difference that actions on an
+    attribute table might also effect the map display.
+    </para>
+
+    <section><title>Table View</title>
+        <para>
+        <figure>
+        <title>Table View</title>
+        <mediaobject>
+        <imageobject><imagedata fileref="../images/7_1_table_view.png" format="PNG" scale="&imgscale;"/></imageobject>
+        <imageobject><imagedata fileref="./images/7_1_table_view.eps" format="EPS" scale="&imgscale;"/></imageobject>
+        </mediaobject>
+        </figure>
+        </para>
+        <para>
+        Thuban provides a standard dialog to display table contents, the 
+        Table View. The view has five sections: The title, selections, 
+        the table grid, export functions, and the status bar.
+        </para>
+        <para>
+        The title bar identifies the table with its name.
+        </para>
+        <para>
+        The selections box let the user perform simple analysis on the data
+        based on comparisons: The first choice must be a field identifier of 
+        the table, the second choice determines the type of comparison. The 
+        third choice can be either a specific value (interpreted as numerical 
+        or string depending on the type of the first field) or a second field 
+        identifier. Thus you can perform analysis like selecting all
+        records where <literal>population > 10000</literal> or 
+        <literal>cars_per_inhabitant < bikes_per_inhabitant</literal> 
+        (note that the field names are only explanatory, the dBase files 
+        allow only 11 character field names).
+      
+        Selections can be combined either by applying a selection only on 
+        a previously selected set of records or by adding the results of a
+        selection to a previous set. The default is that a selection replaces
+        earlier results.
+        </para>
+        <para>
+        The table grid shows the contents of the table (one record per row), 
+        with highlighted selection results. Columns and rows can be resized.
+        </para>
+        <para>
+        The contents of a table can be exported into a file, either dBase
+        format (DBF) or comma separated values (CSV). The 
+        <guibutton>Export</guibutton> button 
+        raises a file dialog to specify a path and file name, the export type
+        is determined by the file extension (either .dbf or .csv).
+
+        The <guibutton>Export Selection</guibutton> button works similarly
+        but exports only the selected records.
+
+        The <guibutton>Close</guibutton> button closes the table view window. 
+        This is different from the menu item 
+        <menuchoice>
+        <guimenu>Table</guimenu>
+        <guimenuitem>Close</guimenuitem>
+        </menuchoice> which unloads the table from Thuban.
+        </para>
+        <para>
+        The status bar displays some statistics about the table and optional
+        selection results.
+        </para>
+    </section>
+
+    <section><title>General Functionality (Menu Table)</title>
+        <para>
+        The general functions affect all tables open in Thuban. Attribute
+        tables are considered here as normal data tables (with the exception
+        that they cannot be closed).
+        </para>
+        <section><title>Open</title>
+            <para>
+            The 
+            <menuchoice>
+            <guimenu>Table</guimenu>
+            <guimenuitem>Open</guimenuitem>
+            </menuchoice> 
+            item raises a file dialog to let you select a 
+            dBase file from the file system to be loaded into Thuban read-only. 
+            On <guibutton>OK</guibutton> the selected file is loaded and a 
+            table view is opened.
+            </para>
+        </section>
+
+        <section><title>Close</title>
+            <para>
+            The
+            <menuchoice>
+            <guimenu>Table</guimenu>
+            <guimenuitem>Close</guimenuitem>
+            </menuchoice> 
+            item raises a dialog listing the currently open 
+            data tables 
+            (loaded via 
+            <menuchoice>
+            <guimenu>Table</guimenu>
+            <guimenuitem>Open</guimenuitem>
+            </menuchoice>). Selected tables are dereferenced on confirmation. 
+            Since tables are opened read-only the contents of the tables are 
+            not affected.
+
+            Any open views of the tables are closed as well.
+
+            Tables used in a join cannot be closed.
+            </para>
+        </section>
+
+        <section><title>Rename</title>
+            <para>
+            <menuchoice>
+            <guimenu>Table</guimenu>
+            <guimenuitem>Rename</guimenuitem>
+            </menuchoice> changes the table title.
+            </para>
+        </section>
+
+        <section><title>Show</title>
+            <para>
+            The
+            <menuchoice>
+            <guimenu>Table</guimenu>
+            <guimenuitem>Show</guimenuitem>
+            </menuchoice> 
+            item raises a list of available tables (explicitly 
+            loaded, attribute tables, results of a join). Selected tables are 
+            show in tables views on <guibutton>OK</guibutton>.
+            </para>
+        </section>
+
+        <section><title>Join</title>
+            <para>
+            <figure>
+            <title>Join Tables</title>
+            <mediaobject>
+            <imageobject><imagedata fileref="../images/7_2_5_join.png" format="PNG" scale="&imgscale;"/></imageobject>
+            <imageobject><imagedata fileref="./images/7_2_5_join.eps" format="EPS" scale="&imgscale;"/></imageobject>
+            </mediaobject>
+            </figure>
+            </para>
+            <para>
+            The 
+            <menuchoice>
+            <guimenu>Table</guimenu>
+            <guimenuitem>Join</guimenuitem>
+            </menuchoice> 
+            item raises a dialog to specify the two tables to be
+            joined. The join results in a new table named 'Join of "left table"
+            and "right table"'.
+
+            The dialog lets you select the two tables to be joined and the two
+            fields the join has to be performed on. By default, the new
+            table contains only those records which are matched by the join.
+
+            If you want to preserve the records of the left table you can 
+            perform an outer join. The fields from the right table for records 
+            not matched by the join are filled with <varname>None</varname> in 
+            this case.
+            </para>
+        </section>
+
+    </section>
+    <section><title>Attribute Tables</title>
+        <para>
+	    To clearly separate between both types of tables (data and 
+        attribute), Thuban provides functionality regarding the attribute 
+        tables under the <menuchoice><guimenu>Layer</guimenu></menuchoice> menu. 
+        </para>
+
+        <section><title>Show Table</title>
+            <para>
+            <menuchoice>
+            <guimenu>Layer</guimenu>
+            <guimenuitem>Show Table</guimenuitem>
+            </menuchoice> 
+            opens the attribute table of the currently active layer in a table 
+            view. 
+
+            In addition to the functionality described above selections
+            affect also the map display: objects related to selected records 
+            are highlighted. 
+            </para>
+        </section>
+
+        <section><title>Join Table</title>
+            <para>
+            Unlike the join described above, the join does not result in a
+            new table. The attribute table of the currently active layer is the
+            left table and other tables are joined to this table. The results of
+            the join are available for classification.
+
+            As a consequence, the join cannot result in fewer
+            records than the source attribute table. The user is warned if the 
+            right table does not fulfill this constraint. An outer join must be
+            used in such cases.
+            </para>
+        </section>
+
+        <section><title>Unjoin Table</title>
+            <para>
+            As said above, a normal table cannot be closed while it is still 
+            used in a join. While the joined table resulting from a join of 
+            normal tables can be simply closed (and thereby dereferencing 
+            the source tables), this is not possible for attribute tables.
+
+            Hence joins on attribute tables must be solved explicitly. This is
+            what the 
+            <menuchoice>
+            <guimenu>Layer</guimenu>
+            <guimenuitem>Unjoin Table</guimenuitem>
+            </menuchoice> 
+            item is used for: The last join for the currently
+            active layer is solved.
+            </para>
+        </section>
+    </section>
+  </chapter>
+
+  <chapter><title>Extensions</title>
+  	<para>
+	Thuban is designed to be extensible. The term Extension is used as a
+	general term for anything that extends Thuban.
+	This chapter introduces into some oppportunities how to add and
+	handle extra functionality developed by your own or third parties.
+	</para>
+
+	<section><title>Add personal extensions via thubanstart.py</title>
+		<para>
+		After Thuban has been started for the first time, a directory
+		.thuban is created within your home directory.
+		There you can add a file thubanstart.py  which will be imported
+		by Thuban at start-up. It is recommended to add only import-statements
+		to this file to keep the actual code of extensions separate.
+		</para>
+		<para>
+		The modules to import must either be found through the environment
+		variable PYTHONPATH or directly be placed into the .thuban-directory.
+		</para>
+		<para>
+		As an example, copy the file examples/simple_extensions/hello_world.py
+		of the Thuban source code into the .thuban-directory of your home
+		directory. Now add add the statement import hello_world to the
+		file thubanstart.py and run Thuban. You will notice an additional
+		menu <menuchoice><guimenu>Extensions</guimenu></menuchoice> where
+		the new item for the Hello-World extension is placed - select it
+		to see the Hello-World message.
+		</para>
+	</section>
+
+	<section><title>Extensions included in Thuban package</title>
+		<para>
+		The extensions described in this section are part of the
+		Thuban package, but not activated by default.
+		You will find them in the Thuban installation directory
+		under <literal>Extensions/</literal>. Activate them as personal
+		extensions via PYTHONPATH as described in the previous section.
+		Stable extensions will appear under the menu
+		<menuchoice><guimenu>Extensions</guimenu></menuchoice> and
+ 		extensions which are in experimental state and therefore
+		not fully functional under
+		<menuchoice><guimenu>Experimental</guimenu></menuchoice>.
+		</para>
+
+		<section><title>Stable extensions</title>
+		    <para>
+		    These extensions provide extra-functionality to Thuban
+		    that has not (yet) been integrated in the main application.
+		    They are considered to be free of bugs, but may be
+		    further polished with helpful user interactions.
+		    </para>
+		    <section><title>gns2shp</title>
+				<para>
+				This tool converts data of the Geospatial Names Server
+				(GNS, see <ulink url="http://www.nima.mil/gns"/>)
+				into Shapefile format.
+				The above web-site offer to download named places
+				information grouped by countries for all of the world
+				except USA for which other data are provided.
+				</para>
+				<para>
+				If you download and unpack a package, you will have
+				a text-file with suffix .txt.
+				Selecting such a file via gns2shp will create the
+				corresponding Shapefile with the same basename and
+				place it in the same direcory. Afterwards it
+				is automatically loaded into Thuban.
+				The Shapefile will not automatically be delete afterwards.
+				</para>
+				<para>
+				The gns2shp.py module can also be executed on the
+				command line for batch processing purposes.
+				</para>
+				<para>
+				A sample (<literal>ls.txt</literal> for Liechtenstein)
+				is included in the directory
+				<literal>Extensions/gns2shp/test</literal>.
+				</para>
+		    </section>
+		    <section><title>SVG Export</title>
+			<para>
+			Map and legend can be exported separately in the 
+			Thuban-Map-SVG format.
+			You get files that comply with 
+			the Scalable Vector Graphics (SVG) 1.1 Specification
+			and can be read by many vector drawing applications.
+			</para>
+			<para>
+			Goal of svgexport is to provide 
+			the start of a printing pipeline for Thuban.
+			For this purpose the written Thuban-Map-SVG files 
+			contain information that can be used in postprocessing.
+			Typically a general vector drawing application is 
+			more powerful then a geographic information viewer;
+			e.g. having much fancier symbols and fonts.
+			Also users benefit much more when learning to use a 
+			more general application they can also use for other
+			tasks.  So the charming idea is to enable 
+			the drawing application to postprocess a Thuban maps.
+			So thee xtra information in the format will make it 
+			possible to export from Thuban and if a few geoobjects
+			change, and keep the general layout and style 
+			of the full map in the vector drawing appplication.
+			</para>
+			<para>
+			Markus Rechtien has developed a prototype of this
+			printing pipline as his Diplom thetis, showing
+			the feasability of Bernhard Reiter's concept.
+			Scripts exist for the drawing application Skencil
+			(<ulink url="http://www.skencil.org"/>).
+			</para>
+			<para>
+			Technical notes: the names of the layers are used
+			as base for ids within the SVG format. 
+			If you try to export with two layers having 
+			the same name, you will get a name clash error.
+			Just change one of the layer names and try again.
+			</para>
+		    </section>
+		</section>
+		<section><title>Experimental extensions</title>
+			<para>
+			All all of these functions have to be handled with care,
+			since they are neither complete nor well tested.
+			They are to be seen as a proof-of-concept and may
+			additionally in some cases of practical help.
+			</para>
+			<para>
+			Any interest on further improvement of these extensions
+			should be communicated towards the developer and user
+			community.
+			</para>
+
+			<section><title>importAPR</title>
+				<para>
+				This command offer to load an ESRI® ArcView® project
+				file (suffix .apr) and convert it for use within Thuban.
+				After selecting a apr-file to load, a list
+				will be presented that offers to select one of the views
+				of the apr-file, provided there is more than one.
+				Furthermore, the Session Info-Tree is extended with
+				a complete representation of the parsed apr-file.
+				</para>
+				<para>
+				The legend of Thuban does not yet cover all of the elements as
+				supported by the legend of ArcView®. Therefore, the Thuban
+				map will look different. Furthermore, the apr-format is
+				a proprietary format, not openly documented.
+				Therefore, the interpretation is
+				partly based on reverse engeneering and good guessing.
+				</para>
+				<para>
+				The file-paths within the apr-file may not fit and potentially
+				are subject to fix in the apr-file. You can do this
+				applying any text editor. The paths are either absolute
+				or relative from where Thuban has been started.
+				</para>
+				<para>
+				A sample for the Iceland data is included as
+				<literal>Extensions/importAPR/samples/iceland.apr</literal>.
+				The file-paths are relative from the Thuban main directory.
+				</para>
+			</section>
+		</section>
+	</section>
+
+	<section><title>Writing simple extensions</title>
+		<para>
+		Writing an extension for Thuban basically means to
+		implement the extra functionality in Python with all of the
+		Thuban classes, methods and variables available.
+		</para>
+		<para>
+		All classes and their methods are documented in the source code
+		(see their doc-strings). Here is an example from
+		Thuban/Model/layer.py that describes some of the methods
+		of a Layer object:
+		</para>
+		<programlisting>
+		<![CDATA[
+class BaseLayer(TitledObject, Modifiable):
+
+    """Base class for the layers."""
+
+    def __init__(self, title, visible = True, projection = None):
+        """Initialize the layer.
+
+        title -- the title
+        visible -- boolean. If true the layer is visible.
+        """
+        TitledObject.__init__(self, title)
+        Modifiable.__init__(self)
+        self.visible = visible
+        self.projection = projection
+
+    def Visible(self):
+        """Return true if layer is visible"""
+        return self.visible
+
+    def SetVisible(self, visible):
+        """Set the layer's visibility."""
+        self.visible = visible
+        self.issue(LAYER_VISIBILITY_CHANGED, self)
+
+    def HasClassification(self):
+        """Determine if this layer support classifications."""
+...
+		]]>
+		</programlisting>
+		<para>
+		This example intends to give you an impression of the
+		source-code-level documentation.
+		You have to make yourself familiar with
+		the Python programming language to understand some special
+		code elements.
+		</para>
+		<section><title>hello_world.py</title>
+		  <para>
+		  Traditionally, the first example should welcome the world.
+		  Most of the code handles the frame for integrating a menu
+		  item into Thuban while the actual raising of a message
+		  is done in a single line.
+		  </para>
+			<programlisting>
+			<![CDATA[
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Extend Thuban with a sample Hello World to demonstrate simple
+extensions.
+"""
+
+__version__ = '$Revision: 2727 $'
+
+# use _() already now for all strings that may later be translated
+from Thuban import _
+
+# Thuban has named commands which can be registered in the central
+# instance registry.
+from Thuban.UI.command import registry, Command
+
+# The instance of the main menu of the Thuban application
+# See Thuban/UI/menu.py for the API of the Menu class
+from Thuban.UI.mainwindow import main_menu
+
+def hello_world_dialog(context):
+    """Just raise a simple dialog to greet the world.
+
+    context -- The Thuban context.
+    """
+    context.mainwindow.RunMessageBox(_('Hello World'), _('Hello World!'))
+
+
+# create a new command and register it
+registry.Add(Command('hello_world', _('Hello World'), hello_world_dialog,
+                     helptext = _('Welcome everyone on this planet')))
+
+# find the extensions menu (create it anew if not found)
+extensions_menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))
+
+# finally bind the new command with an entry in the extensions menu
+extensions_menu.InsertItem('hello_world')
+			]]>
+			</programlisting>
+		</section>
+		<section><title>Registering a Command</title>
+		  <para>
+		  Mainly, our new function has to be registered to the Thuban
+		  framework in order to connect it to the menu. A registered
+		  command can also be connected to e.g. a toolbar button.
+		  </para>
+		  <para>
+		  The instances and classes for this are imported at the beginning.
+		  Any code not inside a method or class is directly executed when
+		  the source-code module is imported. Therefore, the second
+		  part of this example consist of the plain statements to create a new
+		  Command and to add it to the menu.
+		  </para>
+		  <para>
+		  By convention, it looks for a menu registered as ``extensions'' to
+		  insert the new command. If it does not exist yet, it gets created.
+		  It is advisable to copy this code for any of your extensions.
+		  </para>
+		</section>
+		<section><title>The Thuban context</title>
+			<para>
+			A registered command that is called, always receives the
+			Thuban context. This instance provides our method with
+			hook references to all important components of the Thuban
+			application.
+			</para>
+			<para>
+	        In the example hello_world.py, our function uses the
+			mainwindow component which offers a method to raise a
+			message dialog. In total there are three hooks:
+			<itemizedlist>
+			<listitem>
+			<para>application:
+			This object is the instance of the Thuban Application class.
+			Except maybe for loading or savinf sessions, you will not
+			need this object for a simple extension.
+			See Thuban/UI/application.py for the API.
+			</para>
+			</listitem>
+			<listitem>
+			<para>session:
+			The instance of the current session. It manages the sessions'
+			map and tables. You can set and remove the map or tables.
+			In may also get the map object. However, you should know that
+			internally it is already prepared to handle many maps.
+			Therfore, currently you would always receive a list with exactlty
+			one element. In the future, if there are more than one map,
+			you will not know which one is the currently display one and
+			therefore you should use the mainwindow as hook to find
+			the currently displayed map.
+			See Thuban/Model/session.py for the API.
+			</para>
+			</listitem>
+			<listitem>
+			<para>
+			mainwindow: The mainwindow object is central to manage various
+			GUI things such as the Legend sub-window. Most notably,
+			you get access to the canvas which is the window part where
+			the map is drawn. The canvas knows, which map it currently
+			draws and therefore you get the current map via
+			context.mainwindow.canvas.Map().
+			See Thuban/UI/mainwindow.py for the API.
+			</para>
+			</listitem>
+			</itemizedlist>
+            </para>
+		</section>
+	</section>
+  </chapter>
+
+  <chapter><title>Trouble Shooting</title>
+    <para>
+    Here are a few problems that users have encountered when first using Thuban.
+    </para>
+    <para>
+
+    <itemizedlist>
+    <listitem>
+    <para>After adding two or more layers nothing is drawn in the map window.
+    </para>
+    <para>
+    This is probably because the layers have different projections. Projections
+    must be set on all layers and on the map itself if the layers' projections
+    are different.
+    </para>
+    </listitem>
+
+    <listitem>
+    <para>Thuban crashes on startup with the error 
+        <literal>NameError: global name 'False' is not defined</literal>.
+    </para>
+    <para>
+    <varname>True</varname> and <varname>False</varname> were only introduced
+    in Python 2.2.1. Thuban depends on at least Python 2.2.1.
+    </para>
+    </listitem>
+
+    <listitem>
+    <para>After compiling Thuban, Thuban crashes with an error similar to
+        <literal>
+        ImportError: /usr/local//lib/thuban/Thuban/../Lib/wxproj.so: undefined symbol: __gxx_personality_v0
+        </literal>
+    </para>
+    <para>
+    Thuban depends on the wxWindows library. If Thuban is compiled with an
+    incompatible version of the compiler than wxWindows was compiled with
+    this error may occur. Try compiling with a different version of the 
+    compiler.
+    </para>
+    </listitem>
+    </itemizedlist>
+    </para>
+    <para>
+    If an error occurs Thuban will display a dialog indicating the error
+    before closing. The text should be copied and reported to the 
+    <ulink url="http://thuban.intevation.org/bugtracker.html">
+    Intevation bugtracker
+    </ulink>.
+    More information about the system is available from 
+    <menuchoice><guimenu>Help</guimenu><guimenuitem>About</guimenuitem></menuchoice> box.
+    This should also be included in the bug report.
+    <figure>
+    <title>Error Dialog</title>
+    <mediaobject>
+    <imageobject><imagedata fileref="../images/8_int_error.png" format="PNG" scale="&imgscale;"/></imageobject>
+    <imageobject><imagedata fileref="./images/8_int_error.eps" format="EPS" scale="&imgscale;"/></imageobject>
+    </mediaobject>
+    </figure>
+    </para>
+
+  </chapter>
+
+  <appendix><title>Supported Data Sources</title>
+    <para>
+    </para>
+    <variablelist>
+    <varlistentry>
+    <term>Shapefile</term>
+    <listitem>
+        <para>
+        The Shapefile format has become a standard format for saving
+        geographic vector information. It supports polygons, lines, and
+        points. 
+        
+        <ulink url="http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf">
+        Technical Specification.
+        </ulink>  
+        </para>
+    </listitem>
+    </varlistentry>
+
+    <varlistentry>
+    <term>dBase file</term>
+    <listitem>
+        <para>
+        dBase files are used to store the attributes for each layer. This
+        is closely associated with the Shapefile format. For detailed 
+        specifications on the correct format of a dBase file used with
+        Thuban please see the Technical Specification for the Shapefile
+        format above.
+        </para>
+    </listitem>
+    </varlistentry>
+
+    <varlistentry>
+    <term>PostGIS</term>
+    <listitem>
+        <para>
+        PostGIS adds support for geographic objects to the PostgreSQL 
+	object-relational database. Different layer types (as for Shapefiles)
+	are supported. <ulink url="http://postgis.refractions.net">PostGIS
+	Homepage</ulink>
+        </para>
+    </listitem>
+    </varlistentry>
+
+    <varlistentry>
+    <term>Raster files</term>
+    <listitem>
+        <para>
+	Binding the GDAL library Thuban supports numerous raster file formats,
+	see <ulink url="http://www.remotesensing.org/gdal/formats_list.html">
+	GDAL format list</ulink> for details.</para>
+
+	<para>Most commonly used is the <emphasis>TIFF/GeoTIFF</emphasis>
+	format: Raster maps are provided as TIFF images, with an additional 
+	"world file" storing the geographic reference (usually with an
+	extension ".tfw").
+        </para>
+    </listitem>
+    </varlistentry>
+
+    </variablelist>
+  </appendix>
+
+  <appendix><title>Working with PostGIS</title>
+  <para>
+  This section focusses on the use of PostGIS in the Thuban framework. For
+  installation and maintenance of spatial databases we refer to the  
+  <ulink url="http://postgis.refractions.net">PostGIS Homepage</ulink>.
+  The Thuban PostGIS support requires the 
+  <ulink url="http://initd.org/software/psycopg">psycopg module</ulink>.
+  </para>
+
+  <para>
+	Working with PostGIS Databases is seperated into two steps:
+	<itemizedlist>
+	<listitem><para>Opening a Database Connection</para></listitem>
+	<listitem><para>Loading a Data Layer</para></listitem>
+	</itemizedlist>
+  </para>
+	<section><title>Opening a Database Connection</title>
+	<para>
+		Before a data layer can be loaded from a PostGIS database a
+		connection with the database has to be established. 
+		<menuchoice>
+        	<guimenu>Session</guimenu>
+        	<guimenuitem>Database Connections ...</guimenuitem>
+        	</menuchoice> opens a dialog for database connection
+		management. In the dialog new connections can be added 
+		and existing ones can be removed. Removing a database
+		connection is not possible if the map still displays a
+		layer provided by this database connection. 
+	</para>
+    <figure>
+    <title>Database Management Dialog</title>
+    <mediaobject>
+    <imageobject><imagedata fileref="../images/app_postgis_db_management.png" format="PNG" scale="&imgscale;"/></imageobject>
+    <imageobject><imagedata fileref="./images/app_postgis_db_management.eps" format="EPS" scale="&imgscale;"/></imageobject>
+    </mediaobject>
+    </figure>
+
+	<para>
+		To add a new database connection to the session a dialog is
+		opened to specify the relevant connection data. Enter all 
+		data relevant for your connection. If the connection fails 
+		the dialog remains open and provides some hints on the failure.
+	</para>
+        <figure>
+    	<title>Add Database Dialog</title>
+    	<mediaobject>
+    	<imageobject><imagedata fileref="../images/app_postgis_db_add.png" format="PNG" scale="&imgscale;"/></imageobject>
+    	<imageobject><imagedata fileref="./images/app_postgis_db_add.eps" format="EPS" scale="&imgscale;"/></imageobject>
+    	</mediaobject>
+    	</figure>
+	
+	<para>
+	It is important to note that information on database connections are
+	also stored with the session. Passwords are NOT stored. If you load a 
+	session with database connections you are asked to enter these
+	passwords again where required.
+	</para>
+
+	</section>
+
+	<section><title>Loading a Data Layer</title>
+	<para>
+	Data layers as part of a map are loaded with the 
+	<menuchoice>
+        <guimenu>Map</guimenu>
+        <guimenuitem>Add Database Layer ...</guimenuitem>
+        </menuchoice> menu item. A dialog is raised displaying two choice
+	lists. In the left list all connected databases are shown.
+	Highlighting
+	one of these and issuing a retrieval results in a list of available 
+	layer tables from that database. After selection of a 
+	layer the dialog is closed.
+	</para>
+        <figure>
+    	<title>Add Database Dialog</title>
+    	<mediaobject>
+    	<imageobject><imagedata fileref="../images/app_postgis_add_layer.png" format="PNG" scale="&imgscale;"/></imageobject>
+    	<imageobject><imagedata fileref="./images/app_postgis_add_layer.eps" format="EPS" scale="&imgscale;"/></imageobject>
+    	</mediaobject>
+    	</figure>
+	
+	</section>
+
+  </appendix>
+
+  <appendix><title>Supported Projections</title>
+    <para>
+    The following types of projections are directly support by 
+    Thuban. The specific values for each are provided by the user
+    to create custom projections. Thuban comes with predefined
+    projections which are available through the Projections dialog.
+    </para>
+    <itemizedlist>
+    <listitem>
+    	<para>Geographic</para>
+	<itemizedlist>
+    	<listitem><para><literal>Ellipsoid</literal></para></listitem>
+    	<listitem><para>
+		<literal>Source Data</literal>: either Degrees or Radians
+		</para></listitem>
+    	</itemizedlist>
+    </listitem>
+    <listitem>
+    	<para>Lambert Conic Conformal</para>
+    <itemizedlist>
+    	<listitem><para><literal>Ellipsoid</literal></para></listitem>
+    	<listitem><para><literal>Latitude of 1st standard parallel</literal></para></listitem>
+    	<listitem><para><literal>Latitude of 2nd standard parallel</literal></para></listitem>
+    	<listitem><para><literal>Central Meridian</literal></para></listitem>
+    	<listitem><para><literal>Latitude of Origin</literal></para></listitem>
+    	<listitem><para><literal>False Easting</literal> (meters)</para></listitem>
+    	<listitem><para><literal>False Northing</literal> (meters)</para></listitem>
+    </itemizedlist>
+    </listitem>
+    <listitem>
+    	<para>Transverse Mercator</para>
+    <itemizedlist>
+    	<listitem><para><literal>Ellipsoid</literal></para></listitem>
+    	<listitem><para><literal>Latitude</literal>of origin</para></listitem>
+    	<listitem><para><literal>Longitude</literal>at central meridian</para></listitem>
+    	<listitem><para><literal>Scale Factor</literal>at central meridian</para></listitem>
+    	<listitem><para><literal>False Easting</literal> (meters)</para></listitem>
+    	<listitem><para><literal>False Northing</literal> (meters)</para></listitem>
+    </itemizedlist>
+    </listitem>
+    <listitem>
+    	<para>Universal Transverse Mercator</para>
+    <itemizedlist>
+    	<listitem><para><literal>Ellipsoid</literal></para></listitem>
+    	<listitem><para><literal>Zone</literal> 
+		(can be guessed appling the Propose button)</para></listitem>
+    	<listitem><para><literal>Southern Hemisphere</literal> flag</para></listitem>
+    </itemizedlist>
+    </listitem>
+    </itemizedlist>
+    
+    <para>
+    Thuban comes with a sample set of map projections for various 
+    European countries. Apart from the basic projection they differ 
+    especially in their parameterization:
+    </para>
+    <itemizedlist>
+    <listitem><para>Belgium Datum 1972 (Lambert Conic Conformal)</para>
+    </listitem>
+ 
+    <listitem><para>Gauss-Boaga Zone 1 (Italy, Transverse Mercartor)</para>
+    </listitem>
+ 
+    <listitem><para>Gauss-Krueger Zone 2 (Germany, Transverse Mercartor)
+    </para>
+    </listitem>
+ 
+    <listitem><para>Reseau Geodesique Francaise 
+    (France, Lambert Conic Conformal)</para>
+    </listitem>
+ 
+    <listitem><para>UK National Grid (United Kingdom, Transverse Mercartor)
+    </para>
+    </listitem>
+    </itemizedlist>
+
+    <para>
+    Thuban uses the comprehensive PROJ library for projections. PROJ provides
+    more than the four commonly used projections described above. If needed
+    Thuban can be easily extended to a new projection covered by PROJ.
+    </para>
+  </appendix>
+
+</book>
+

Added: packages/thuban/branches/upstream/current/Doc/technotes/README
===================================================================
--- packages/thuban/branches/upstream/current/Doc/technotes/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/technotes/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,21 @@
+Readme for Thuban's Doc/devnotes
+================================
+Author: Bernhard Herzog <bh at intevation.de>
+Last-Modified: $Date: 2004-02-26 12:22:30 +0100 (Do, 26 Feb 2004) $
+Version: $Revision: 2093 $
+
+
+Overview
+
+    This directory contains a collection of documents for Thuban
+    developers.  Each file is a plain text file formatted more or less
+    like the plaintext Python PEPs [1].
+
+
+References
+
+    [1] http://python.org/peps/pep-0009.html
+	Sample Plaintext PEP Template
+
+
+

Added: packages/thuban/branches/upstream/current/Doc/technotes/coding_guidelines.txt
===================================================================
--- packages/thuban/branches/upstream/current/Doc/technotes/coding_guidelines.txt	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/technotes/coding_guidelines.txt	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,130 @@
+Title: Coding Guidelines for Thuban
+Author: Bernhard Herzog <bh at intevation.de>
+Last-Modified: $Date: 2006-04-20 15:20:48 +0200 (Do, 20 Apr 2006) $
+Version: $Revision: 2678 $
+
+
+Introduction
+
+    To keep the Thuban code maintainable all code should adhere to the
+    guidelines outlined below.  The guidelines currently cover stylistic
+    issues (e.g. rules for source code formatting) as well as Python
+    programming hints and rules for using SVN and making patches.
+
+
+Source Formatting
+
+    Python and, where applicable, C/C++ source code should be formatted
+    according to these rules:
+
+    - All lines should be at most 79 characters long
+
+    - Put spaces around binary operators and after commas, colons and
+      semicolons.  Do not put spaces before commas, colons and
+      semicolons and don't put them after opening or before closing
+      parentheses, brackets and braces.
+
+    - Use only spaces for indentation.  Each indentation level is four
+      spaces.
+
+    - Every class, function and method should have a doc string.  The
+      doc string should start with a brief one-line description of the
+      class or method.  If more explanations are needed add an empty
+      line and one or more paragraphs.
+
+    - Put imports at the top of a module.  Put the more fundamental
+      import statements first, and the more Thuban specific later.
+      E.g. imports from the standard library come first, then import
+      statements for third-party modules, then Thuban imports.  Imports
+      from the same Thuban sub-package come last.
+
+
+Python Programming
+
+    - Thuban must remain compatible with Python 2.2.
+
+    - Do not use "from module import *"
+
+      This form of the import statement leads to code that is hard to
+      maintain for several reasons:
+
+      - When the module's contents change, the names bound in the code
+        that executes the import statement change as well and might
+        accidentally override python builtins or names already bound in
+        the module
+
+      - It's hard to find out which of the objects in the imported
+        module are actually used by the importing code.  It's especially
+        hard to find out whether the import is still needed if the code
+        has changed.
+
+    - Do not check the type of parameters
+
+      Functions and methods should be coded to interfaces, not types, so
+      checking whether an object passed as a parameter to a function is
+      of a certain type or an instance of a particular class is almost
+      never a good idea.
+
+    - Use "obj is None" when testing for None not just "obj".  The
+      object in question might be false without being None.
+
+    - Method names start with lower case letter.
+
+      The main reason is that we should, in the long term, adopt the more
+      common naming styles used in python code.  For Thuban this basically
+      means not to start method names with upper case letters. For Thuban this
+      would be a substantial change and even though it would be easy to retain
+      the old method names for a while for backwards compatibility it's not
+      something that should be done soon.  However, new classes should
+      follow this rule.
+
+Test Suite
+
+    Thuban has a fairly comprehensive test suite in the test/
+    subdirectory.  The test suite is only useful if it is kept up to
+    date and if it is run often.  Therefore:
+
+    - Before a checkin, run the *entire testsuite*.  Yes, all of it.
+      Even if you think your change won't break anything.
+
+    - New functionality and bug fixes should have corresponding tests in
+      the test suite.
+
+    - The tests should use only public interfaces.
+
+    - Write the tests before writing the code.
+
+    - It should be possible to run the test suite without an X server
+      being present.
+
+
+SVN
+
+    - One can't say this often enough: Before a checkin, run the *entire
+      testsuite*.  Yes, all of it.  Even if you think your change won't
+      break anything.
+
+    - All commits should be described in the ChangeLog file.  The easiest
+      way to do that is to write the ChangeLog entry first and use that
+      as the commit message. Maybe your editor has support to help with this.
+
+    - Try to make small self contained commits.  In particular, if
+      during the work on a more complex change you discover a bug,
+      commit the the fix to that bug separately with a separate
+      ChangeLog entry.
+
+Patches
+
+    - When you produce patches please try to produce them as patches
+      against a current SVN version.  A patch against code from a
+      tarball is often OK too but can make it more difficult to test a
+      patch if e.g. the files in SVN have changed considerably.
+
+    - Please make context diffs, i.e. use the -c or -u option of diff or svn
+      diff.  The default output of diff is not suitable for a patch.
+
+    - Treat a patch like SVN commit.  That is what it will end up as if
+      it is accepted, so if you want to increase the chances that it
+      will be applied, please try to make the work easier for us, and
+      make sure the test suite still works, add new tests if your patch
+      adds functionality or fixes a bug and write a ChangeLog entry.

Added: packages/thuban/branches/upstream/current/Doc/technotes/release_process.txt
===================================================================
--- packages/thuban/branches/upstream/current/Doc/technotes/release_process.txt	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/technotes/release_process.txt	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,83 @@
+Title: The Thuban Release Process
+Author: Thuban development team
+Last-Modified: $Date: 2007-02-20 10:51:07 +0000 (Di, 20 Feb 2007) $
+Version: $Revision: 2728 $
+
+How to Release a New Thuban Version
+
+    - Test Thuban until you are sure it works under the following
+      reference platforms:
+
+      Debian GNU/Linux 4.0 (aka Etch) (plus wxWindows/wxPython 2.6)
+      (Windows XP)
+
+      All test cases of stable code should pass on all platforms.
+
+    - Adjust revision number in setup.py and Thuban/version.py.  See the
+      comments in version.py for details.
+
+    - Update thuban.pot and the various .po and .mo files:
+
+      cd po/
+      make pot
+      make update-po
+      make mo
+
+      See po/README for details
+
+    - Update MANIFEST.in
+
+      This is only necessary if the set of files distributed has changed
+      in such a way that the old MANIFEST.in doesn't fit anymore. This
+      could be e.g. the addition of a new top-level directory such as
+      Extensions
+
+    - Produce Source-Archives Thuban-N.N.N.tar.gz and Thuban-N.N.N.zip
+ 
+        python setup.py sdist
+
+
+Old:- Build a binary for W2000: Thuban-N.N.N-1.exe
+
+      On a Windows system with Inno Setup installed, unpack the source
+      archive (usually the zip file) and run:
+
+        python setup.py bdist_inno
+
+      Test the resulting setup program.
+
+Old:- Build RPMs for RedHat 7.2
+
+      Take the source tarball and, on a RedHat 7.2 system, run:
+
+        python setup.py bdist_rpm
+
+      Install the rpm and test Thuban. Make sure to have removed any
+      other Thuban rpms beforehand.
+
+    - Produce Sample-Data-Tarballs
+
+        python setup.py data_dist
+
+Old:- Tag the tested sources for CVS:
+
+        cvs tag THUBAN_N_N_N
+
+Old:- Place packages on ftp server at ftp://intevation.de/thuban/
+
+Old:- Update http://thuban.intevation.org/download.html accordingly
+
+    - Update/Extend http://thuban.intevation.org/screenshots.html
+      if there have been interesting changes/extensions to the UI.
+
+    - Make sure you closed all open issues that were solved with this
+      release.
+
+    - Write announcement including all major improvements.
+
+Old:    - Send announcement to following mailing lists:
+      thuban-list at intevation.de
+      freegis-list at intevation.de
+
+    - Have a beer and thank all contributors :-)
+

Added: packages/thuban/branches/upstream/current/Doc/technotes/string_representation.txt
===================================================================
--- packages/thuban/branches/upstream/current/Doc/technotes/string_representation.txt	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Doc/technotes/string_representation.txt	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,85 @@
+Title: String Representation in Thuban
+Author: Bernhard Herzog <bh at intevation.de>
+Last-Modified: $Date: 2005-07-01 22:49:04 +0200 (Fr, 01 Jul 2005) $
+Version: $Revision: 2642 $
+
+
+Introduction
+
+    Thuban originally assumed that text is represented by byte-strings
+    encoded in ISO-8859-1 (latin-1).  This is problematic when the
+    default encoding in the user's locale is not in fact latin-1, but
+    e.g. UTF-8.  The solution is to use a more flexible representation
+    that will also allow the switch to Unicode as the internal string
+    representation at one point.
+
+
+Internal String Representation
+
+    Thuban has an internal string representation.  All textual data read
+    by Thuban has to be converted to the internal representation.  All
+    data written by Thuban has to be converted into whatever form is
+    used by the output device.
+
+    Thuban provides functions to convert between the internal
+    representation and other representations.  E.g.:
+    internal_from_unicode which converts from unicode and should be used
+    when reading XML files, for instance and unicode_from_internal for
+    the conversion to Unicode.
+
+    The ultimate goal is to use Unicode objects as the internal string
+    representation.  It will be much work to get there because we will
+    have to find all the places where we need to make the conversions.
+    Therefore the internal representation will be byte strings in the
+    user's default encoding.  
+
+    With byte strings and especially encodings like latin-1 we can get
+    by without doing all the conversions correctly because basically all
+    byte strings are valid latin-1 strings, even if they have the wrong
+    encoding.  In those cases, the text may look strange, but there
+    won't be exceptions in most cases.  With Unicode objects, exceptions
+    are much more likely.  And in the end it's better to see some
+    incorrect characters than no data at all.
+
+    All this boils down to the following steps:
+
+    1. Byte-Strings as Internal Representation
+
+    The internal representation are byte strings in the user's default
+    encoding as determined by the locale.  The encoding is chosen so
+    that such byte strings can be passed to wxPython without problems.
+    This even works with Unicode builds if we take care to convert the
+    translated strings (wxGetTranslation returns Unicode objects in a
+    Unicode build).
+
+    If no suitable encoding can be determined, use latin-1.  It might be
+    better to use ASCII instead, but latin 1 offers somewhat better
+    backwards compatibility with older Thuban versions.
+
+    Start implementing the conversion functions and use them wherever
+    we have hard coded conversions to latin-1.  It's not necessary to
+    find all places where conversion has to be done at this point.
+    Since we're using byte strings in the user's default encoding most
+    byte-strings that are read by Thuban are already in the right form
+    and in most cases it's also the right form for output.
+
+
+    2. Implement the conversion wherever necessary
+
+    Start working toward Unicode as the internal representation.  In
+    this phase, we need to find all places where conversion has to be
+    done.  To help with this, there will be a command line option that
+    sets the internal representation to Unicode so that it's easy to
+    test.
+
+    The most difficult areas for this are probably the various data
+    sources.  Some of them -- dbf files for instance -- q don't provide
+    any information about the encodings used.
+
+
+    3. Switch to Unicode
+
+    Finally, switch to Unicode as the internal string representation.
+    For this step it might be best to wait until Unicode builds of
+    wxPython are the default on the common platforms.
+

Added: packages/thuban/branches/upstream/current/Examples/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Examples/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Examples/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,6 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.

Added: packages/thuban/branches/upstream/current/Examples/simple_extensions/README
===================================================================
--- packages/thuban/branches/upstream/current/Examples/simple_extensions/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Examples/simple_extensions/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,11 @@
+Simple Example Extensions for Thuban
+------------------------------------
+
+This directory contains some simple extensions for Thuban that show how
+you can add commands and tools to Thuban.
+
+To run an examples, make sure this directory in your python path and
+import one or more of the modules in it in ~/.thuban/thubanstart.py.
+Create that file and directory if it doesn't exist yet. It is
+automatically executed by Thuban if it exists.
+

Added: packages/thuban/branches/upstream/current/Examples/simple_extensions/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Examples/simple_extensions/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Examples/simple_extensions/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,6 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.

Added: packages/thuban/branches/upstream/current/Examples/simple_extensions/hello_world.py
===================================================================
--- packages/thuban/branches/upstream/current/Examples/simple_extensions/hello_world.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Examples/simple_extensions/hello_world.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,44 @@
+# Copyright (C) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Extend Thuban with a sample Hello World to demonstrate simple
+extensions.
+"""
+
+__version__ = '$Revision: 2409 $'
+# $Source$
+# $Id: hello_world.py 2409 2004-11-20 21:57:14Z jan $
+
+# use _() already now for all strings that may later be translated
+from Thuban import _
+
+# Thuban has named commands which can be registered in the central
+# instance registry.
+from Thuban.UI.command import registry, Command
+
+# The instance of the main menu of the Thuban application
+# See Thuban/UI/menu.py for the API of the Menu class
+from Thuban.UI.mainwindow import main_menu
+
+def hello_world_dialog(context):
+    """Just raise a simple dialog to greet the world.
+
+    context -- The Thuban context.
+    """
+    context.mainwindow.RunMessageBox(_('Hello World'), _('Hello World!'))
+
+
+# create a new command and register it
+registry.Add(Command('hello_world', _('Hello World'), hello_world_dialog,
+                     helptext = _('Welcome everyone on this planet')))
+
+# find the extensions menu (create it anew if not found)
+examples_menu = main_menu.FindOrInsertMenu('examples', _('&Examples'))
+
+# finally bind the new command with an entry in the extensions menu
+examples_menu.InsertItem('hello_world')

Added: packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_command.py
===================================================================
--- packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_command.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_command.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,60 @@
+# Copyright (C) 2002, 2004 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de> (2002)
+# Jan-Oliver Wagner <jan at intevation.de> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Extend thuban with a simple command.
+"""
+
+__version__ = "$Revision: 2410 $"
+# $Source$
+# $Id: simple_command.py 2410 2004-11-20 21:57:43Z jan $
+
+# First import some things we need later.
+import os
+from Thuban.UI.command import registry, Command
+from Thuban.UI.mainwindow import main_menu
+
+# a function implementing a command. Such a function is called with one
+# argument describing the context in which it is invoked. The context is
+# an object with a few public attributes for the application object, the
+# session and the main window.
+def simple_command(context):
+    print "simple_command: Application", context.application
+    print "simple_command: Session", context.session
+    print "simple_command: Main window", context.mainwindow
+    print "simple_command: Map", context.mainwindow.canvas.Map()
+
+# Add the command to the registry. A command is represented by a Command
+# instance which is instantiated with four parameters here, the name of
+# the command, it's title, the function to call when the command is
+# invoked by the user and a help text to show in the statusbar.
+#
+# The name is used internally to identify commands. The title is
+# displayed in the menus.
+registry.Add(Command("simple_command", "Simple Command", simple_command,
+                     helptext = "Simple Command"))
+
+# The main menu is defined by the main_menu object in
+# Thuban.UI.mainwindow. This object has a few methods to add new menus
+# and menu items.
+#
+# FindOrInsertMenu creates a new submenu in the menu, parameters are its name
+# and title which have the same meanings as for a command. The return
+# value is a menu object for the new submenu which has the same methods
+# as main_menu.
+# If the menu already exist, this previous one will be returned an
+# no new one be created.
+menu = main_menu.FindOrInsertMenu("examples", "&Examples")
+
+# In the new menu we can add new items with InsertItem which takes the
+# name of a command as parameter or with InsertSeparator to add a
+# separator. We can also use InsertMenu to add submenus, of course. We
+# add the command twice here to demonstrate separators.
+menu.InsertItem("simple_command")
+menu.InsertSeparator()
+menu.InsertItem("simple_command")

Added: packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_tool.py
===================================================================
--- packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_tool.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_tool.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,109 @@
+# Copyright (C) 2002, 2004 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de> (2002)
+# Jan-Oliver Wagner <jan at intevation.de> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Extend thuban with a simple tool.
+"""
+
+__version__ = "$Revision: 2411 $"
+# $Source$
+# $Id: simple_tool.py 2411 2004-11-20 21:58:18Z jan $
+
+# First import some things we need later.
+import os
+from math import hypot
+from Thuban.UI.command import registry, ToolCommand
+from  Thuban.UI.mainwindow import main_toolbar
+from Thuban.UI.viewport import Tool
+
+
+# A tool is a class usually derived from the Tool class. The tool class
+# provides some standard methods to handle mouse events. It maintains a
+# few instance variables that can be used when processing mouse events:
+# self.start is the point where the user started to drag, self.current
+# is the current position, self.dragging is true while the user is
+# moving the mouse with the (left) button pressed.
+
+class SimpleTool(Tool):
+
+    """A Simple Tool"""
+
+    def Name(self):
+        """Return the string 'SimpleTool'."""
+        # The return value is used to identify tools easily
+        return "SimpleTool"
+
+    def map_distance(self):
+        """Return the distance on the map between the start and current point
+        """
+        # self.view is the canvas window the tool instance is working
+        # on. Its win_to_proj method computes the coordinates in the
+        # projected map coordinates for a given point in window
+        # coordinates
+        sx, sy = apply(self.view.win_to_proj, self.start)
+        x, y = apply(self.view.win_to_proj, self.current)
+        return hypot(x - sx, y - sy)
+
+    def MouseMove(self, event):
+        """Called by the canvas window when the mouse moves"""
+        # The self.dragging flag is true, if the user is currently
+        # dragging the mouse. Code in the Tool class has already handled
+        # the button press event to set this flag.
+        if self.dragging:
+            # Call the inherited method to update some internal data
+            # (self.start, etc.)
+            Tool.MouseMove(self, event)
+            print "SimpleTool: current distance", self.map_distance()
+
+    def MouseUp(self, event):
+        if self.dragging:
+            Tool.MouseUp(self, event)
+            print "SimpleTool: final distance", self.map_distance()
+
+
+# the function implementing the "SimpleTool" command. Set the tool of
+# the canvas to SimpleTool
+def simple_tool(context):
+    canvas = context.mainwindow.canvas
+    canvas.SelectTool(SimpleTool(canvas))
+
+
+# Add the command to the registry. A command is represented by a Command
+# instance. Here it's instantiated with the the name of the command,
+# it's title and the function to call when the command is invoked by the
+# user as positional arguments. The name is used internally to identify
+# commands. The title is displayed in the menus.
+#
+# The icon keyword argument is optional and only useful if the command
+# is used in a toolbar. It should be the name of an XPM file without the
+# .xpm extension which will be automatically appended. We assume here
+# that the icon's XPM file is located in the same directory as this
+# module.
+#
+# The helptext keyword argument is an optional helptext.
+#
+# The checked keyword argument is an optional function to determine
+# whether the button or menu item should be checked. It's called with
+# the context. If the checked argument is not given the button or menu
+# item will be a normal command button/item.
+
+def check_simple_tool(context):
+    """Return if the current tool of the context is the simple tool"""
+    # the CurrentTool() method of the canvas returns the result of the
+    # tool's Name method so we just have to compare it to "SimpleTool"
+    return context.mainwindow.canvas.CurrentTool() == "SimpleTool"
+
+iconfile = os.path.abspath(os.path.join(os.path.split(__file__)[0],
+                                        "simple_tool"))
+registry.Add(ToolCommand("simple_tool", "Simple Tool", simple_tool,
+                         icon = iconfile, helptext = "Simple Tool",
+                         checked = check_simple_tool))
+
+# Add the command to the toolbar
+main_toolbar.InsertSeparator()
+main_toolbar.InsertItem("simple_tool")

Added: packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_tool.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_tool.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Examples/simple_extensions/simple_tool.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,29 @@
+/* XPM */
+static char * measure_xpm[] = {
+"24 24 2 1",
+" 	c None",
+".	c #000000",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"    .      ...     .    ",
+"   .       .        .   ",
+"  .......  ..   ......  ",
+"   .         .      .   ",
+"    .      ..      .    ",
+"  .                  .  ",
+"  .                  .  ",
+"  ....................  ",
+"  .                  .  ",
+"  .                  .  ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Extensions/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,6 @@
+# Copyright (c) 2003 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.

Added: packages/thuban/branches/upstream/current/Extensions/bboxdump/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/bboxdump/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/bboxdump/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 by Intevation GmbH
+# Authors:
+# Frank Koormann <frank at intevation.de> (2004)
+# Jan-Oliver Wagner <jan at intevation.de> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+# import the actual module
+import bboxdump
+
+# perform the registration of the extension
+from Thuban import _
+from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+
+ext_registry.add(ExtensionDesc(
+    name = 'bboxdump',
+    version = '1.0.0',
+    authors= [ 'Frank Koormann' ],
+    copyright = '2004 Intevation GmbH',
+    desc = _("Dumps the bounding boxes of all\n" \
+             "shapes of the selected layer.")))

Added: packages/thuban/branches/upstream/current/Extensions/bboxdump/bboxdump.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/bboxdump/bboxdump.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/bboxdump/bboxdump.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,244 @@
+# Copyright (C) 2004 by Intevation GmbH
+# Authors:
+# Frank Koormann <frank at intevation.de> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Extend thuban with a bounding box dump.
+
+Dumps the bounding boxes of all shapes of the selected layer.
+An optional column can be specified to group the objects, 
+in this case the bounding box is a union of the separate boxes.
+"""
+
+__version__ = '$Revision: 2721 $'
+# $Source$
+# $Id: bboxdump.py 2721 2007-01-13 15:11:42Z dpinte $
+
+import os, sys
+import string
+
+import wx
+from wx.lib.dialogs import ScrolledMessageDialog
+
+from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
+from Thuban.UI.command import registry, Command
+from Thuban.UI.mainwindow import main_menu, _has_selected_shape_layer
+from Thuban import _
+
+import shapelib
+import dbflib
+
+# Widget IDs
+ID_FILENAME = 4001
+ID_ATTRIBUTES = 4002
+ID_SELFN = 4003
+
+class BBoxDumpDialog(wx.Dialog):
+    """Bounding Box Dump Dialog
+
+    Specify a filename for the dump and optionally a layer's column 
+    field to group objects.
+    """
+
+    def __init__(self, parent, title, layer = None):
+        wx.Dialog.__init__(self, parent, -1, title,
+                          style = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
+
+        if layer is None:
+            return wx.ID_CANCEL
+
+        # Store the layer
+        self.layer = layer
+
+        # Filename selection elements
+        self.filename = wx.TextCtrl(self, ID_FILENAME, "")
+        self.button_selectfile = wx.Button(self, ID_SELFN, _('Select...'))
+        wx.EVT_BUTTON(self, ID_SELFN, self.OnSelectFilename)
+
+        # Column choice elements
+        self.choice_column = wx.Choice(self, ID_ATTRIBUTES)
+        self.choice_column.Append(_('Select...'), None)
+        for col in self.layer.ShapeStore().Table().Columns():
+                self.choice_column.Append(col.name, col)
+        self.choice_column.SetSelection(0)
+
+        # Dialog button elements
+        self.button_dump = wx.Button(self, wx.ID_OK, _("OK"))
+        wx.EVT_BUTTON(self, wx.ID_OK, self.OnDump)
+        self.button_dump.SetDefault()
+        # TODO: Disable the OK button until a filename is entered ...
+        # self.button_dump.Enable(False)
+        self.button_cancel = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+
+
+        # Dialog Layout: three horizontal box sizers.
+        topbox = wx.BoxSizer(wx.VERTICAL)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        topbox.Add(hbox, 0, wx.ALL|wx.EXPAND)
+        hbox.Add(wx.StaticText(self, -1, _("File:")),
+                 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        hbox.Add(self.filename, 1, wx.ALL|wx.EXPAND, 4)
+        hbox.Add(self.button_selectfile, 0, wx.ALL, 4)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        topbox.Add(hbox, 0, wx.ALL|wx.EXPAND)
+        hbox.Add(wx.StaticText(self, -1, _("Group by:")),
+                 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        hbox.Add(self.choice_column, 1, wx.ALL|wx.EXPAND, 4)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        topbox.Add(hbox, 0, wx.ALL|wx.EXPAND)
+        hbox.Add(self.button_dump, 0, wx.ALL|wx.ALIGN_CENTER,
+                  10)
+        hbox.Add(self.button_cancel, 0, wx.ALL|wx.ALIGN_CENTER,
+                  10)
+
+        # Finalize ...
+        self.SetAutoLayout(True)
+        self.SetSizer(topbox)
+        topbox.Fit(self)
+        topbox.SetSizeHints(self)
+
+        # Store for later use
+        self.parent = parent
+
+    def OnDump(self, event):
+        """Bounding Box Dump Dialog event handler OK button.
+
+        Prepare the inputs from the dialog and call processing.
+        """
+        i = self.choice_column.GetSelection()
+        column = self.choice_column.GetClientData(i)
+        self.Close()
+
+        ThubanBeginBusyCursor()
+        try:
+            bboxmessage = bboxdump(self.layer, column, self.filename.GetValue())
+        finally:
+            ThubanEndBusyCursor()
+
+        if bboxmessage:
+            dlg = ScrolledMessageDialog(
+                                self.parent, bboxmessage,
+                                _("Bounding Box Dump %s") % self.layer.Title())
+            dlg.ShowModal()
+
+    def OnSelectFilename(self, event):
+        """Bounding Box Dump Dialog event handler File Selection.
+
+        Opens a file dialog to specify a file to dump into.
+        """
+        dlg = wx.FileDialog(self, _("Dump Bounding Boxes To"), 
+                       os.path.dirname(self.filename.GetValue()), 
+                       os.path.basename(self.filename.GetValue()),
+                       _("CSV Files (*.csv)|*.csv|") +
+                       _("All Files (*.*)|*.*"),
+                       wx.SAVE|wx.OVERWRITE_PROMPT)
+        if dlg.ShowModal() == wx.ID_OK:
+            self.filename.SetValue(dlg.GetPath())
+            dlg.Destroy()
+        else:
+            dlg.Destroy()
+
+
+def bboxdump(layer, column, filename):
+    """Bounding Box Dump Processing
+
+    layer    - Layer of shapes to be dumped
+    column   - optional column to group shapes (else None)
+    filename - optional filename to dump into (else empty string, i.e. dump
+           to message dialog)
+    """
+    # Preparation
+    shapelist = {}
+    bboxmessage = []
+ 
+    dlg= wx.ProgressDialog(_("Bounding Box Dump"),
+                          _("Collecting shapes ..."),
+                          layer.ShapeStore().NumShapes(),
+                          None)
+
+    cnt = 0
+    step =  int(layer.ShapeStore().NumShapes() / 100.0)
+    if step == 0:
+        step = 1
+
+    # Collect shape ids to be dumped
+    if column is None:
+        # A simple dump of shapes bbox is required
+        for s in layer.ShapeStore().AllShapes():
+            i = s.ShapeID()
+            shapelist[i] = (i,)
+            if cnt % step == 0:
+                dlg.Update(cnt)
+            cnt = cnt + 1
+    else:
+        # group them by column ... 
+        for s in layer.ShapeStore().AllShapes():
+            i = s.ShapeID()
+            row = layer.ShapeStore().Table().ReadRowAsDict(i)
+            att = row[column.name]
+            if not shapelist.has_key(att):
+                shapelist[att] = []
+            shapelist[att].append(i)
+            if cnt % step == 0:
+                dlg.Update(cnt)
+            cnt = cnt + 1
+
+    dlg.Destroy()
+    dlg= wx.ProgressDialog(_("Bounding Box Dump"),
+                          _("Dump bounding boxes of selected shapes ..."),
+                          len(shapelist),
+                          None)
+    cnt = 0
+    step = int(len(shapelist) / 100.0)
+    if step == 0:
+        step = 1
+
+    # Dump them, sorted
+    keys = shapelist.keys()
+    keys.sort()
+    for key in keys:
+        bbox = layer.ShapesBoundingBox(shapelist[key])
+        bboxmessage.append("%.3f,%.3f,%.3f,%.3f,%s\n" % (
+                            bbox[0], bbox[1], bbox[2], bbox[3], key))
+        if cnt % step == 0:
+            dlg.Update(cnt)
+        cnt = cnt + 1
+    dlg.Destroy()
+
+    # finally
+    if filename != '':
+        bboxfile = file(filename, 'w+')
+        bboxfile.write(string.join(bboxmessage))
+        bboxfile.close()
+        return None
+    else:
+        return string.join(bboxmessage)
+
+def LayerBBoxDump(context):
+    """Menu Handler BBoxDump
+    """
+    layer = context.mainwindow.canvas.SelectedLayer()
+    if layer is not None:
+        dlg = BBoxDumpDialog(context.mainwindow, _("Bounding Box Dump"),
+                             layer = layer)
+        dlg.ShowModal()
+
+
+# bboxdump executed as an extension to Thuban
+
+# register the new command
+registry.Add(Command('bboxdump', _('BBox Dump'), LayerBBoxDump,
+                     helptext = _('Dump Bounding Boxes of Layer Objects'),
+                     sensitive = _has_selected_shape_layer))
+
+# find the extensions menu (create it anew if not found)
+extensions_menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))
+
+# finally add the new entry to the extensions menu
+extensions_menu.InsertItem('bboxdump')

Added: packages/thuban/branches/upstream/current/Extensions/drawshape/README
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/drawshape/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/drawshape/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,47 @@
+Draw Shape Extension for Thuban
+===============================
+
+
+   *** Warning: ***
+
+   This extension is very experimental and may corrupt your data. Use at
+   your own peril.
+
+   The installation instructions here are very brief to make it more
+   likely that people who use it know what they're doing.
+
+
+
+Summary
+-------
+
+This extension for Thuban allows you do add shapes to shapefiles.
+
+
+
+Installation
+------------
+
+1. Apply the patch in patch.diff
+
+2. Put the drawshape.py somewhere where you can import it from
+   ~/.thuban/thubanstart.py and add the appropriate import statement to
+   thuban/thubanstart.py
+
+
+Usage
+-----
+
+The extension adds a new icon to the toolbar. This icon is the same as
+the one for the identify tool because there wasn't time to create a new
+one :)
+
+To add a shape, select the layer you want to add to, activate the tool
+and draw the shape by clicking on the map where the vertices should be
+with the left mouse button. When done, click the right button and the
+shape will be added to the shapefile with a set of default attributes
+(zeros and empty strings).
+
+The layer must be a layer displaying a shapefile with polygons (arcs and
+points are not supported) and the associated table must be a real dbf
+file and not e.g. a joined table.

Added: packages/thuban/branches/upstream/current/Extensions/drawshape/drawshape.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/drawshape/drawshape.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/drawshape/drawshape.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,155 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Extension to draw polygons
+
+*** Warning: ***
+
+This extension is very experimental and may corrupt your data. Use at
+your own peril.
+"""
+
+__version__ = "$Revision: 2207 $"
+# $Source$
+# $Id: drawshape.py 2207 2004-05-16 09:30:34Z jan $
+
+
+import os
+
+from wxPython.wx import *
+
+import shapelib
+import Thuban
+from Thuban import _
+from Thuban.Model.data import SHAPETYPE_POLYGON
+from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_STRING, \
+     FIELDTYPE_DOUBLE
+from Thuban.UI.command import registry, ToolCommand
+from Thuban.UI.mainwindow import main_menu, main_toolbar
+from Thuban.UI.viewport import Tool
+
+
+def write_empty_row(table, row):
+    """Write an empty record to the row
+
+    The values in the record will be set to suitable default values
+    depending on the type: 0 for numeric types and the empty string for
+    strings.
+    """
+    values = {}
+    for col in table.Columns():
+        if col.type == FIELDTYPE_INT:
+            value = 0
+        elif col.type == FIELDTYPE_DOUBLE:
+            value = 0.0
+        elif col.type == FIELDTYPE_STRING:
+            value = ""
+        else:
+            print "write_empty_row: Unhandled col.type", col.type
+        values[col.name] = value
+    table.write_record(row, values)
+
+
+def write_shape(shapestore, points):
+    """Addd the points as a new shape to the shapestore
+
+    The points argument should be a list of the same structure as that
+    returned by the shapelib bindings for a polygon. It is passed
+    directly to the SHPObject constructor.
+    """
+    shapefile = shapelib.ShapeFile(shapestore.FileName(), "r+b")
+    obj = shapelib.SHPObject(shapelib.SHPT_POLYGON, 1, points)
+    newid = shapefile.write_object(-1, obj)
+    write_empty_row(shapestore.Table(), newid)
+    shapefile.close()
+    shapestore._open_shapefile()
+
+
+class ShapeDrawTool(Tool):
+
+    def __init__(self, view):
+        Tool.__init__(self, view)
+        self.points = []
+
+    def Name(self):
+        return "ShapeDrawTool"
+
+    def find_shapestore(self):
+        """Return the shapestore into which to write and the projection
+
+        If the currently selected layer is a layer with polygons return
+        a tuple of the shapestore and the layer's projection.
+        Otherwise return a tuple of Nones.
+        """
+        layer = self.view.SelectedLayer()
+        if layer is not None and layer.HasShapes() \
+               and layer.ShapeType() == SHAPETYPE_POLYGON:
+            return layer.ShapeStore(), layer.GetProjection()
+        return None, None
+
+    def MouseDown(self, event):
+        Tool.MouseDown(self, event)
+        if event.RightDown():
+            map_proj = self.view.Map().GetProjection()
+            shapestore, proj = self.find_shapestore()
+            if shapestore is not None and len(self.points) > 2:
+                points = self.points[:]
+                if map_proj is not None:
+                    points = [tuple(map_proj.Inverse(*p)) for p in points]
+                if proj is not None:
+                    points = [tuple(proj.Forward(*p)) for p in points]
+                points.append(points[0])
+                write_shape(shapestore, [points])
+                self.points = []
+                self.view.full_redraw()
+        else:
+            if not self.points:
+                self.points.append(self.view.win_to_proj(*self.current))
+
+    def MouseUp(self, event):
+        Tool.MouseUp(self, event)
+        self.points.append(self.view.win_to_proj(*self.current))
+
+    def draw(self, dc):
+        points = [self.view.proj_to_win(*p) for p in self.points] \
+                 + [self.current]
+        if len(points) == 2:
+            dc.DrawLines(points)
+        else:
+            dc.DrawPolygon(points)
+
+    def DrawPermanent(self, dc):
+        dc.SetPen(wxPen(wxColor(255, 128, 0), 2))
+        dc.SetBrush(wxTRANSPARENT_BRUSH)
+        dc.DrawPolygon([self.view.proj_to_win(*p) for p in self.points])
+
+
+def shape_draw_tool(context):
+    canvas = context.mainwindow.canvas
+    canvas.SelectTool(ShapeDrawTool(canvas))
+
+def check_shape_draw_tool(context):
+    return context.mainwindow.canvas.CurrentTool() == "ShapeDrawTool"
+
+
+iconfile = os.path.join(os.path.abspath(Thuban.__path__[0]),
+                        "..", "Resources", "Bitmaps", "identify")
+registry.Add(ToolCommand("shape_draw_tool", "Shape Draw Tool",
+                         shape_draw_tool, icon = iconfile,
+                         helptext = "Draw a shape",
+                         checked = check_shape_draw_tool))
+
+# Add the command to the toolbar
+main_toolbar.InsertSeparator()
+main_toolbar.InsertItem("shape_draw_tool")
+
+# find the experimental menu (create it anew if not found)
+experimental_menu = main_menu.FindOrInsertMenu('experimental',
+                                               _('Experimenta&l'))
+
+# finally add the new command to the experimental menu
+experimental_menu.InsertItem('shape_draw_tool')

Added: packages/thuban/branches/upstream/current/Extensions/drawshape/patch.diff
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/drawshape/patch.diff	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/drawshape/patch.diff	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,87 @@
+Index: Thuban/UI/view.py
+===================================================================
+RCS file: /thubanrepository/thuban/Thuban/UI/view.py,v
+retrieving revision 1.59
+diff -c -r1.59 view.py
+*** Thuban/UI/view.py	27 Oct 2003 13:01:58 -0000	1.59
+--- Thuban/UI/view.py	25 Nov 2003 13:10:15 -0000
+***************
+*** 128,133 ****
+--- 128,134 ----
+          EVT_PAINT(self, self.OnPaint)
+          EVT_LEFT_DOWN(self, self.OnLeftDown)
+          EVT_LEFT_UP(self, self.OnLeftUp)
++         wx.EVT_RIGHT_DOWN(self, self.OnRightDown)
+          EVT_MOTION(self, self.OnMotion)
+          EVT_LEAVE_WINDOW(self, self.OnLeaveWindow)
+          wx.EVT_SIZE(self, self.OnSize)
+***************
+*** 140,145 ****
+--- 141,150 ----
+      def PreviewBitmap(self):
+          return self.bitmap
+  
++     def SelectTool(self, tool):
++         ViewPort.SelectTool(self, tool)
++         self.redraw()
++ 
+      def PanTool(self):
+          """Start the canvas pan tool"""
+          self.SelectTool(CanvasPanTool(self))
+***************
+*** 170,175 ****
+--- 175,182 ----
+                  dc.DrawBitmap(self.bitmap, 0, 0)
+                  if self.selection_bitmap is not None:
+                      dc.DrawBitmap(self.selection_bitmap, 0, 0, True)
++                 if self.tool is not None:
++                     self.tool.DrawPermanent(dc)
+                  dc.EndDrawing()
+          else:
+              # If we've got no map or if the map is empty, simply clear
+***************
+*** 384,389 ****
+--- 391,400 ----
+                  self.drag_dc = None
+                  self.dragging = 0
+          self.MouseLeftUp(event)
++         self.redraw()
++ 
++     def OnRightDown(self, event):
++         self.MouseRightDown(event)
+  
+      def OnMotion(self, event):
+          if self.dragging:
+Index: Thuban/UI/viewport.py
+===================================================================
+RCS file: /thubanrepository/thuban/Thuban/UI/viewport.py,v
+retrieving revision 1.15
+diff -c -r1.15 viewport.py
+*** Thuban/UI/viewport.py	6 Oct 2003 17:31:31 -0000	1.15
+--- Thuban/UI/viewport.py	25 Nov 2003 13:10:15 -0000
+***************
+*** 80,85 ****
+--- 80,88 ----
+      def draw(self, dc):
+          pass
+  
++     def DrawPermanent(self, dc):
++         pass
++ 
+      def MouseDown(self, event):
+          self.drag_start(event.m_x, event.m_y)
+  
+***************
+*** 598,603 ****
+--- 601,611 ----
+          self.set_current_position(event)
+          if self.tool is not None:
+              self.tool.MouseUp(event)
++ 
++     def MouseRightDown(self, event):
++         self.set_current_position(event)
++         if self.tool is not None:
++             self.tool.MouseDown(event)
+  
+      def MouseMove(self, event):
+          self.set_current_position(event)

Added: packages/thuban/branches/upstream/current/Extensions/export_shapefile/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/export_shapefile/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/export_shapefile/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,23 @@
+# Copyright (c) 2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2005)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+# perform the registration of the extension
+from Thuban import _
+from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+
+def init():
+    """Initialize storeshape extension module."""
+    import export_shapefile
+    return None
+
+ext_registry.add(ExtensionDesc(
+    name = 'export_shapefile',
+    version = '0.1.0',
+    authors= [ 'Jan-Oliver Wagner' ],
+    copyright = '2005 Intevation GmbH',
+    desc = _("Exports the selected layer as a Shapefile."),
+    init_callback = init))

Added: packages/thuban/branches/upstream/current/Extensions/export_shapefile/export_shapefile.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/export_shapefile/export_shapefile.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/export_shapefile/export_shapefile.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,98 @@
+# Copyright (C) 2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2005)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Extend Thuban with a routine to export a layer
+as a Shapefile.
+"""
+
+__version__ = '$Revision: 2724 $'
+# $Source$
+# $Id: export_shapefile.py 2724 2007-02-20 10:25:11Z bernhard $
+
+import wx
+
+from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
+                              SHAPETYPE_POINT
+from Thuban.Model.table import table_to_dbf
+from Thuban.UI.command import registry, Command
+from Thuban.UI.mainwindow import main_menu
+from Thuban import _
+
+import shapelib
+
+def ExportLayerAsShapefile(context):
+    """Request filename from user, 
+    and create the Shapefile(s) .shp, .dbf and .shx.
+
+    context -- The Thuban context.
+    """
+    # First, find the current layer
+    layer = context.mainwindow.canvas.SelectedLayer()
+    if layer is None:
+       context.mainwindow.RunMessageBox(_('Export Shapefile'),
+           _('No layer selected'))
+       return
+
+    # Second, get the basefilename for the shapefile.
+    dlg = wx.FileDialog(context.mainwindow,
+                       _('Export Shapefile'), '.', '',
+                       _('Shapefile  Files (*.shp)|*.shp|'),
+                       wx.SAVE|wx.OVERWRITE_PROMPT)
+    if dlg.ShowModal() == wx.ID_OK:
+        filename = dlg.GetPath()[:-4]
+        dlg.Destroy()
+    else:
+        return
+
+    # Third, create the dbf file of the new Shapefile
+    dbf_filename = filename + '.dbf'
+    if hasattr(layer, "ShapeStore"):
+        table = layer.ShapeStore().Table()
+        table_to_dbf(table, dbf_filename)
+
+    # Fourth, prepare the shp file of the new Shapefile
+    shp_filename = filename + '.shp'
+    shapetypes = { SHAPETYPE_POLYGON: shapelib.SHPT_POLYGON,
+        SHAPETYPE_ARC: shapelib.SHPT_ARC,
+        SHAPETYPE_POINT: shapelib.SHPT_POINT}
+    shp = shapelib.create(shp_filename, shapetypes[layer.ShapeType()])
+
+    # Now go through all shapes and store them to the file
+    dlg= wx.ProgressDialog(_("Export Shapefile"),
+                          _("Storing shapes ..."),
+                          layer.ShapeStore().NumShapes(),
+                          None)
+
+    cnt = 0
+    step =  int(layer.ShapeStore().NumShapes() / 100.0)
+    if step == 0: step = 1
+
+    for s in layer.ShapeStore().AllShapes():
+        i = s.ShapeID()
+        print s.Points()
+        obj = shapelib.SHPObject(shapetypes[layer.ShapeType()], i, s.Points())
+        shp.write_object(i, obj)
+        if cnt % step == 0:
+            dlg.Update(cnt)
+        cnt = cnt + 1
+
+    del shp
+    dlg.Destroy()
+
+
+# register the new command
+registry.Add(Command('ExportShapefile', _('Export Layer as Shapefile ...'),
+                     ExportLayerAsShapefile,
+                     helptext = _('Export the active layer as a Shapefile')))
+
+# find the experimental menu (create it anew if not found)
+experimental_menu = main_menu.FindOrInsertMenu("experimental", \
+                                              _("Experimenta&l"))
+
+# finally add the new entry to the extensions menu
+experimental_menu.InsertItem('ExportShapefile')

Added: packages/thuban/branches/upstream/current/Extensions/gns2shp/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/gns2shp/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/gns2shp/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,25 @@
+# Copyright (c) 2003-2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2003-2005)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+# perform the registration of the extension
+from Thuban import _
+from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+
+def init():
+    """Initialize gns2shp extension module."""
+    import gns2shp
+    return None
+
+ext_registry.add(ExtensionDesc(
+    name = 'gns2shp',
+    version = '1.0.0',
+    authors= [ 'Jan-Oliver Wagner' ],
+    copyright = '2003, 2004 Intevation GmbH',
+    desc = _("Converts GNS (Geographical Name Service\n" \
+             "of NIMA) to Shapefile format and\n" \
+             "displays the data."),
+    init_callback = init))

Added: packages/thuban/branches/upstream/current/Extensions/gns2shp/gns2shp.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/gns2shp/gns2shp.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/gns2shp/gns2shp.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,185 @@
+# Copyright (C) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Extend thuban with a gns2shp converter.
+
+This module also works without Thuban on the command line
+if the shapelib and dbflib python wrappers can be found via the
+PYTHONPATH (e.g. via including directory 'Lib' of thuban directory).
+
+The GUI should eventually be extended to allow pre-selection
+of the points to import in order to reduce immense quantities
+of some country files.
+"""
+
+__version__ = '$Revision: 2721 $'
+# $Source$
+# $Id: gns2shp.py 2721 2007-01-13 15:11:42Z dpinte $
+
+import os, sys
+
+# only import GUI and register when not called as command line tool
+if __name__ != '__main__':
+    import wx
+
+    from Thuban.UI.command import registry, Command
+    from Thuban.UI.mainwindow import main_menu
+    from Thuban import _
+    from Thuban.Model.layer import Layer
+
+import shapelib
+import dbflib
+
+def gns2shp(src_fname, dest_fname):
+    """Convert a file from gns textformat into a Shapefile.
+
+    The GNS text format is described on
+    http://www.nima.mil/gns/html/gis.html
+
+    src_fname  -- Filename of the GNS standard textfile (including suffix '.txt)
+    dest_fname -- Filename where to write the Shapefile components (name
+                  without suffix). After successful completion there
+                  will be files "dest_fname".shp, "dest_fname".shx and
+                  "dest_fname.dbf".
+
+    Return: Number of sucessfully converted entries
+    """
+    gns_filename = src_fname
+    shp_filename = dest_fname + '.shp'
+    dbf_filename = dest_fname + '.dbf'
+
+    gns = open(gns_filename, 'r').readlines()
+
+    shp = shapelib.create(shp_filename, shapelib.SHPT_POINT)
+    dbf = dbflib.create(dbf_filename)
+    dbf.add_field('RC', dbflib.FTInteger, 1, 0)
+    dbf.add_field('UFI', dbflib.FTInteger, 10, 0)
+    dbf.add_field('UNI', dbflib.FTInteger, 10, 0)
+    dbf.add_field('UTM', dbflib.FTString, 4, 0)
+    dbf.add_field('JOG', dbflib.FTString, 7, 0)
+    dbf.add_field('FC', dbflib.FTString, 1, 0)
+    dbf.add_field('DSG', dbflib.FTString, 5, 0)
+    dbf.add_field('PC', dbflib.FTInteger, 1, 0)
+    dbf.add_field('CC1', dbflib.FTString, 2, 0)
+    dbf.add_field('ADM1', dbflib.FTString, 2, 0)
+    dbf.add_field('ADM2', dbflib.FTString, 200, 0)
+    dbf.add_field('DIM', dbflib.FTInteger, 10, 0)
+    dbf.add_field('CC2', dbflib.FTString, 2, 0)
+    dbf.add_field('NT', dbflib.FTString, 1, 0)
+    dbf.add_field('LC', dbflib.FTString, 2, 0)
+    dbf.add_field('SHORT_FORM', dbflib.FTString, 128, 0)
+    dbf.add_field('GENERIC', dbflib.FTString, 128, 0)
+    dbf.add_field('SORT_NAME', dbflib.FTString, 200, 0)
+    dbf.add_field('FULL_NAME', dbflib.FTString, 200, 0)
+    dbf.add_field('FULL_ND', dbflib.FTString, 200, 0) # FULL_NAME_ND
+    dbf.add_field('MODIFY_DATE', dbflib.FTString, 11, 0)
+    del dbf
+    dbf = dbflib.open(dbf_filename, 'r+b')
+
+    gns.pop(0) # drop the header line
+
+    i = 0
+    for line in gns:
+        if line[0] == '#': continue
+        RC, UFI, UNI, DD_LAT, DD_LONG, DMS_LAT, DMS_LONG, UTM, \
+            JOG, FC, DSG, PC, CC1, ADM1, ADM2, DIM, CC2, NT, LC, \
+            SHORT_FORM, GENERIC, SORT_NAME, FULL_NAME, FULL_NAME_ND, \
+            MODIFY_DATE  = line.split('\t')
+        RC = int(RC)
+        UFI = int(UFI)
+        UNI = int(UNI)
+        DD_LAT = float(DD_LAT)
+        DD_LONG = float(DD_LONG)
+        try: PC = int(PC)
+        except: PC = None
+        try: DIM = int(DIM)
+        except: DIM = None
+        MODIFY_DATE = MODIFY_DATE[0:10] # kill trailing "\n" or "\r\n"
+        obj = shapelib.SHPObject(shapelib.SHPT_POINT, i, [[(DD_LONG, DD_LAT)]])
+        shp.write_object(-1, obj)
+        dbf.write_record(i, { 'RC': RC, 'UFI': UFI, 'UNI': UNI, 'UTM': UTM,
+                              'JOG': JOG, 'FC': FC, 'DSG': DSG, 'PC': PC,
+                              'CC1': CC1, 'ADM1': ADM1, 'ADM2': ADM2,
+                              'DIM': DIM, 'CC2': CC2, 'NT': NT, 'LC': LC,
+                              'SHORT_FORM': SHORT_FORM, 'GENERIC': GENERIC,
+                              'SORT_NAME': SORT_NAME, 'FULL_NAME': FULL_NAME,
+                              'FULL_ND': FULL_NAME_ND,
+                              'MODIFY_DAT': MODIFY_DATE})
+        i += 1
+
+    del shp
+    del dbf
+
+    return i
+
+def gns2shp_dialog(context):
+    """Request filename from user, run conversion and add
+    resulting shapefile to the current map.
+
+    context -- The Thuban context.
+    """
+    dlg = wx.FileDialog(context.mainwindow,
+                       _('Select GNS file'), '.', '',
+                       _('Generate Files (*.txt)|*.txt|') +
+                       _('All Files (*.*)|*.*'),
+                       wx.OPEN|wx.OVERWRITE_PROMPT)
+    if dlg.ShowModal() == wx.ID_OK:
+        gns_filename = dlg.GetPath()
+        dlg.Destroy()
+    else:
+        return
+
+    no = gns2shp(gns_filename, gns_filename[:-4])
+    if no <= 0:
+        context.mainwindow.RunMessageBox(_('gns2shp'), _('Conversion failed'))
+        return
+    else:
+        context.mainwindow.RunMessageBox(_('gns2shp %s') % __version__,
+                                         _('%d locations converted' % no))
+
+    # Now load the newly created shapefile
+    filename = gns_filename[:-4] + '.shp'
+    title = os.path.splitext(os.path.basename(filename))[0]
+    map = context.mainwindow.canvas.Map()
+    has_layers = map.HasLayers()
+    try:
+        store = context.session.OpenShapefile(filename)
+    except IOError:
+        # the layer couldn't be opened
+        context.mainwindow.RunMessageBox(_('Add GNS Layer'),
+                           _("Can't open the file '%s'.") % filename)
+    else:
+        layer = Layer(title, store)
+        map.AddLayer(layer)
+        if not has_layers:
+            # if we're adding a layer to an empty map, fit the
+            # new map to the window
+            context.mainwindow.canvas.FitMapToWindow()
+
+if __name__ == '__main__': # gns2shp executed as a command line tool
+    print 'gns2shp.py %s' % __version__
+    if len(sys.argv) == 3:
+        no = gns2shp(sys.argv[1], sys.argv[2][:-4])
+        print '%d locations converted' % no
+        sys.exit(0)
+    else:
+        print 'usage: gns2shp.py GNS-file Shapefile'
+        sys.exit(1)
+
+
+# gns2shp executed as an extension to Thuban
+
+# register the new command
+registry.Add(Command('gns2shp', _('gns2shp...'), gns2shp_dialog,
+                     helptext = _('Convert GNS-file into a shapefile')))
+
+# find the extensions menu (create it anew if not found)
+extensions_menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))
+
+# finally add the new entry to the extensions menu
+extensions_menu.InsertItem('gns2shp')

Added: packages/thuban/branches/upstream/current/Extensions/gns2shp/test/README
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/gns2shp/test/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/gns2shp/test/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,10 @@
+This directory contains tests of the gns2shl extension.
+
+About file "ls.txt":
+
+LIECHTENSTEIN  LS  2002-11-08  1999-01  1988-01  3
+retrieved from:
+http://www.nima.mil/gns/html/cntry_files.html
+
+Run test with:
+python test_gns2shp.py

Added: packages/thuban/branches/upstream/current/Extensions/gns2shp/test/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/gns2shp/test/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/gns2shp/test/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,6 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.

Added: packages/thuban/branches/upstream/current/Extensions/gns2shp/test/ls.txt
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/gns2shp/test/ls.txt	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/gns2shp/test/ls.txt	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,89 @@
+RC	UFI	UNI	DD_LAT	DD_LONG	DMS_LAT	DMS_LONG	UTM	JOG	FC	DSG	PC	CC1	ADM1	ADM2	DIM	CC2	NT	LC	SHORT_FORM	GENERIC	SORT_NAME	FULL_NAME	FULL_NAME_ND	MODIFY_DATE
+1	-1187145	-1749126	47.0666667	9.5000000	470400	93000	NT31	NL32-02	A	ADM1 		LS	00				N				BALZERS	Balzers	Balzers	1993-12-22
+1	-1187146	-1749127	47.0666667	9.5000000	470400	93000	NT31	NL32-02	P	PPL		LS	00				N				BALZERS	Balzers	Balzers	1993-12-22
+1	-1187147	-1749128	47.2166667	9.5000000	471300	93000	NT32	NL32-02	P	PPL		LS	00				N				BENDERN	Bendern	Bendern	1993-12-22
+1	-1187148	-1749129	47.0666667	9.6166667	470400	93700	NT41	NL32-02	T	PASS 		LS	00				N				BETTLERJOCH	Bettlerjoch	Bettlerjoch	1993-12-22
+1	-1187170	-1749130	47.1833333	9.5333333	471100	93200	NT42	NL32-02	P	PPL		LS	00				V				BLANKEN	Blanken	Blanken	1993-12-22
+1	-1187149	-1749131	47.1666667	9.5500000	471000	93300	NT42	NL32-02	T	MTS		LS	00				N				DREISCHWESTERN	Drei Schwestern	Drei Schwestern	1993-12-22
+1	-1187149	-1749132	47.1666667	9.5500000	471000	93300	NT42	NL32-02	T	MTS		LS	00				V				DREYSCHWESTERN	Drey Schwestern	Drey Schwestern	1993-12-22
+1	419575	535546	47.1500000	9.5166667	470900	93100	NT32	NL32-02	P	PPL		LS	00				V				EBAHOLZ	Ebaholz	Ebaholz	1999-01-26
+1	419575	535575	47.1500000	9.5166667	470900	93100	NT32	NL32-02	P	PPL		LS	00				N				EBENHOLZ	Ebenholz	Ebenholz	1999-01-26
+1	-1187152	-1749133	47.0500000	9.5666667	470300	93400	NT41	NL32-02	T	MT		LS	00				V				ENDERLINHORN	Enderlin Horn	Enderlin Horn	1993-12-22
+1	-1187150	-1749134	47.2166667	9.5166667	471300	93100	NT32	NL32-02	A	ADM1 		LS	00				N				ESCHEN	Eschen	Eschen	1993-12-22
+1	-1187151	-1749135	47.2166667	9.5166667	471300	93100	NT32	NL32-02	P	PPL		LS	00				N				ESCHEN	Eschen	Eschen	1993-12-22
+1	-1187150	-1749136	47.2166667	9.5166667	471300	93100	NT32	NL32-02	A	ADM1 		LS	00				V				ESCHENNEDELN	Eschen-Nedeln	Eschen-Nedeln	1993-12-22
+1	-1187152	-1749137	47.0500000	9.5666667	470300	93400	NT41	NL32-02	T	MT		LS	00				N				FALKNIS	Falknis	Falknis	1993-12-22
+1	-1187152	-1749138	47.0500000	9.5666667	470300	93400	NT41	NL32-02	T	MT		LS	00				V				FALKNISHORN	Falknis Horn	Falknis Horn	1993-12-22
+1	-1187153	-1749139	47.2000000	9.5833333	471200	93500	NT42	NL32-02	T	MT		LS	00				N				FRASTANZERSAND	Frastanzer Sand	Frastanzer Sand	1993-12-22
+1	-1187154	-1749140	47.1333333	9.5500000	470800	93300	NT42	NL32-02	T	MT		LS	00				N				FURSTENSTEIG	Fürstensteig	Furstensteig	1993-12-22
+1	419573	535544	47.1333333	9.5333333	470800	93200	NT42	NL32-02	P	PPL		LS	00				N				GAFLEI	Gaflei	Gaflei	1999-01-26
+1	-1187155	-1749141	47.1500000	9.6166667	470900	93700	NT42	NL32-02	T	MT		LS	00				N				GALLINAKOPF	Gallinakopf	Gallinakopf	1993-12-22
+1	-1187157	-1749142	47.2166667	9.5000000	471300	93000	NT32	NL32-02	P	PPL		LS	00				V				GAMBRIN	Gambrin	Gambrin	1993-12-22
+1	-1187156	-1749143	47.2166667	9.5000000	471300	93000	NT32	NL32-02	A	ADM1 		LS	00				N				GAMPRIN	Gamprin	Gamprin	1993-12-22
+1	-1187157	-1749144	47.2166667	9.5000000	471300	93000	NT32	NL32-02	P	PPL		LS	00				N				GAMPRIN	Gamprin	Gamprin	1993-12-22
+1	-1187156	-1749145	47.2166667	9.5000000	471300	93000	NT32	NL32-02	A	ADM1 		LS	00				V				GAMPRINBENDERN	Gamprin-Bendern	Gamprin-Bendern	1993-12-22
+1	-1187158	-1749146	47.1666667	9.5666667	471000	93400	NT42	NL32-02	T	MT		LS	00				N				GARSELLAKOPF	Garsellakopf	Garsellakopf	1993-12-22
+1	-1187160	-1749147	47.0500000	9.5833333	470300	93500	NT41	NL32-02	T	PK		LS	00				V				GRAUSPITZ	Grauspitz	Grauspitz	1993-12-22
+1	-1187192	-1749148	47.0500000	9.5833333	470300	93500	NT41	NL32-02	T	PK		LS	00				V				GRAUSPITZ	Grauspitz	Grauspitz	1993-12-22
+1	-1187159	-1749149	47.2333333	9.5333333	471400	93200	NT43	NL32-02	P	PPLX 		LS	00				N				HINTERERSCHELLENBERG	Hinterer Schellenberg	Hinterer Schellenberg	1993-12-22
+1	-1187160	-1749150	47.0500000	9.5833333	470300	93500	NT41	NL32-02	T	PK		LS	00				N				HINTERGRAUSPITZ	Hinter-Grauspitz	Hinter-Grauspitz	1993-12-22
+1	419566	535536	47.0500000	9.5500000	470300	93300	NT41	NL32-02	T	VAL		LS	00				N				LAWENA	Lawena	Lawena	1999-01-26
+1	-1187161	-1749151	47.1666667	9.5333333	471000	93200	NT42	NL32-02	A	PCLI 		LS	00				V				LICHTENSTEIN	Lichtenstein	Lichtenstein	1996-11-29
+1	-1187161	-1749152	47.1666667	9.5333333	471000	93200	NT42	NL32-02	A	PCLI 		LS	00				V				LIECHTENSTEIN	Liechtenstein	Liechtenstein	1996-11-29
+1	-1187161	-1749154	47.1666667	9.5333333	471000	93200	NT42	NL32-02	A	PCLI 		LS	00				N	GM	Liechtenstein	Fürstentum	LIECHTENSTEIN FURSTENTUM	Fürstentum Liechtenstein	Furstentum Liechtenstein	1996-11-29
+1	-1187161	-1749153	47.1666667	9.5333333	471000	93200	NT42	NL32-02	A	PCLI 		LS	00				C		Liechtenstein		LIECHTENSTEIN PRINCIPALITYOF	Principality of Liechtenstein	Principality of Liechtenstein	1996-11-29
+1	419565	535533	47.0500000	9.5000000	470300	93000	NT31	NL32-02	P	PPL		LS	00				N				MALS	Mäls	Mals	1999-01-26
+1	419572	535543	47.1333333	9.5333333	470800	93200	NT42	NL32-02	P	PPL		LS	00				N				MASESCHA	Masescha	Masescha	1999-01-26
+1	-1187162	-1749155	47.1333333	9.6166667	470800	93700	NT42	NL32-02	T	PASS 		LS	00				V				MATLAJOCH	Matla Joch	Matla Joch	1994-04-28
+1	-1187162	-1749159	47.1333333	9.6166667	470800	93700	NT42	NL32-02	T	PASS 		LS	00			AU	N				MATLERJOCH	Matlerjoch	Matlerjoch	1994-04-28
+1	-1187181	-1749157	47.1333333	9.6333333	470800	93800	NT42	NL32-02	T	MT		LS	00				V				MATLERKOPF	Matler Kopf	Matler Kopf	1993-12-22
+1	-1187162	-1749158	47.1333333	9.6166667	470800	93700	NT42	NL32-02	T	PASS 		LS	00			LS	N				MATTAJOCH	Mattajoch	Mattajoch	1994-04-28
+1	-1187164	-1749160	47.2166667	9.5333333	471300	93200	NT42	NL32-02	P	PPL		LS	00				V				MAUERN	Mauern	Mauern	1993-12-22
+1	-1187163	-1749161	47.2166667	9.5333333	471300	93200	NT42	NL32-02	A	ADM1 		LS	00				N				MAUREN	Mauren	Mauren	1993-12-22
+1	-1187164	-1749162	47.2166667	9.5333333	471300	93200	NT42	NL32-02	P	PPL		LS	00				N				MAUREN	Mauren	Mauren	1993-12-22
+1	-1187163	-1749163	47.2166667	9.5333333	471300	93200	NT42	NL32-02	A	ADM1 		LS	00				V				MAURENSCHAANWALD	Mauren-Schaanwald	Mauren-Schaanwald	1993-12-22
+1	-1187165	-1749164	47.2333333	9.5333333	471400	93200	NT43	NL32-02	P	PPLX 		LS	00				N				MITTLERERSCHELLENBERG	Mittlerer Schellenberg	Mittlerer Schellenberg	1993-12-22
+1	419574	535545	47.1500000	9.5000000	470900	93000	NT32	NL32-02	P	PPL		LS	00				V				MOLIHOLZ	Möliholz	Moliholz	1999-01-26
+1	419574	535574	47.1500000	9.5000000	470900	93000	NT32	NL32-02	P	PPL		LS	00				N				MUHLEHOLZ	Mühleholz	Muhleholz	1999-01-26
+1	-1187166	-1749165	47.0500000	9.6000000	470300	93600	NT41	NL32-02	T	MT		LS	00				N				NAAFKOPF	Naafkopf	Naafkopf	1993-12-22
+1	-1187166	-1749166	47.0500000	9.6000000	470300	93600	NT41	NL32-02	T	MT		LS	00				V				NAUFKOPF	Nauf Kopf	Nauf Kopf	1993-12-22
+1	-1187167	-1749167	47.2000000	9.5500000	471200	93300	NT42	NL32-02	P	PPL		LS	00				N				NENDELN	Nendeln	Nendeln	1993-12-22
+1	-1187168	-1749168	47.1166667	9.6333333	470700	93800	NT41	NL32-02	T	MT		LS	00				V				OCHSENBERG	Ochsenberg	Ochsenberg	1993-12-22
+1	-1187168	-1749169	47.1166667	9.6333333	470700	93800	NT41	NL32-02	T	MT		LS	00				N				OCHSENKOPF	Ochsenkopf	Ochsenkopf	1993-12-22
+1	-1187169	-1749170	47.1833333	9.5333333	471100	93200	NT42	NL32-02	A	ADM1 		LS	00				N				PLANKEN	Planken	Planken	1993-12-22
+1	-1187170	-1749171	47.1833333	9.5333333	471100	93200	NT42	NL32-02	P	PPL		LS	00				N				PLANKEN	Planken	Planken	1993-12-22
+1	-1187171	-1749172	47.0500000	9.7500000	470300	94500	NT51	NL32-02	T	MTS		LS	00				V				RATIKON	Rätikon	Ratikon	1993-12-22
+1	-1187171	-1749174	47.0500000	9.7500000	470300	94500	NT51	NL32-02	T	MTS		LS	00				V				RHAETIKON	Rhaetikon	Rhaetikon	1993-12-22
+1	-1187171	-1749175	47.0500000	9.7500000	470300	94500	NT51	NL32-02	T	MTS		LS	00				N				RHATIKON	Rhätikon	Rhatikon	1993-12-22
+1	-1187171	-1749176	47.0500000	9.7500000	470300	94500	NT51	NL32-02	T	MTS		LS	00				V				RHATIKONMOUNTAINS	Rhätikon Mountains	Rhatikon Mountains	1993-12-22
+1	419569	535539	47.1166667	9.5500000	470700	93300	NT41	NL32-02	P	PPL		LS	00				V				ROTABODA	Rotaboda	Rotaboda	1999-01-26
+1	419569	535573	47.1166667	9.5500000	470700	93300	NT41	NL32-02	P	PPL		LS	00				N				ROTENBODEN	Rotenboden	Rotenboden	1999-01-26
+1	-1187174	-1749189	47.2333333	9.5166667	471400	93100	NT33	NL32-02	P	PPL		LS	00				V				RUGELL	Rugell	Rugell	1993-12-22
+1	-1187173	-1749190	47.2333333	9.5166667	471400	93100	NT33	NL32-02	A	ADM1 		LS	00				N				RUGGELL	Ruggell	Ruggell	1993-12-22
+1	-1187174	-1749191	47.2333333	9.5166667	471400	93100	NT33	NL32-02	P	PPL		LS	00				N				RUGGELL	Ruggell	Ruggell	1993-12-22
+1	-1187175	-1749192	47.2333333	9.6333333	471400	93800	NT43	NL32-02	H	STM		LS	00				N				SAMINA	Samina	Samina	1993-12-22
+1	-1187176	-1749193	47.1666667	9.5833333	471000	93500	NT42	NL32-02	T	VAL		LS	00				N				SAMINATAL	Saminatal	Saminatal	1993-12-22
+1	-1187176	-1749194	47.1666667	9.5833333	471000	93500	NT42	NL32-02	T	VAL		LS	00				V				SAMINATHAL	Samina Thal	Samina Thal	1993-12-22
+1	-1187177	-1749195	47.1000000	9.6333333	470600	93800	NT41	NL32-02	T	PASS 		LS	00				N				SAREISERJOCH	Sareiser Joch	Sareiser Joch	1993-12-22
+1	-1187178	-1749196	47.1666667	9.5000000	471000	93000	NT32	NL32-02	A	ADM1 		LS	00				N				SCHAAN	Schaan	Schaan	1993-12-22
+1	-1187179	-1749197	47.1666667	9.5000000	471000	93000	NT32	NL32-02	P	PPL		LS	00				N				SCHAAN	Schaan	Schaan	1993-12-22
+1	-1187180	-1749198	47.2166667	9.5666667	471300	93400	NT42	NL32-02	P	PPL		LS	00				N				SCHAANWALD	Schaanwald	Schaanwald	1993-12-22
+1	-1187179	-1749199	47.1666667	9.5000000	471000	93000	NT32	NL32-02	P	PPL		LS	00				V				SCHAN	Schan	Schan	1993-12-22
+1	-1187181	-1749200	47.1333333	9.6333333	470800	93800	NT42	NL32-02	T	MT		LS	00				N				SCHEIENKOPF	Scheienkopf	Scheienkopf	1993-12-22
+1	-1187182	-1749201	47.2333333	9.5333333	471400	93200	NT43	NL32-02	A	ADM1 		LS	00				N				SCHELLENBERG	Schellenberg	Schellenberg	1993-12-22
+1	-1187183	-1749202	47.2333333	9.5333333	471400	93200	NT43	NL32-02	P	PPL		LS	00				N				SCHELLENBERG	Schellenberg	Schellenberg	1993-12-22
+1	-1187181	-1749203	47.1333333	9.6333333	470800	93800	NT42	NL32-02	T	MT		LS	00				V				SCHEUENKOPF	Scheuenkopf	Scheuenkopf	1993-12-22
+1	419570	535541	47.1333333	9.5500000	470800	93300	NT42	NL32-02	P	PPL		LS	00				N				SILUM	Silum	Silum	1999-01-26
+1	419568	535538	47.1166667	9.5666667	470700	93400	NT41	NL32-02	P	PPL		LS	00				N				SUCKA	Sücka	Sucka	1999-01-26
+1	-1187184	-1749204	47.1000000	9.5333333	470600	93200	NT41	NL32-02	A	ADM1 		LS	00				N				TRIESEN	Triesen	Triesen	1993-12-22
+1	-1187185	-1749205	47.1000000	9.5333333	470600	93200	NT41	NL32-02	P	PPL		LS	00				N				TRIESEN	Triesen	Triesen	1993-12-22
+1	-1187186	-1749206	47.1166667	9.5333333	470700	93200	NT41	NL32-02	A	ADM1 		LS	00				N				TRIESENBERG	Triesenberg	Triesenberg	1993-12-22
+1	-1187187	-1749207	47.1166667	9.5333333	470700	93200	NT41	NL32-02	P	PPL		LS	00				N				TRIESENBERG	Triesenberg	Triesenberg	1993-12-22
+1	-1187188	-1749208	47.2500000	9.5333333	471500	93200	NT43	NL32-02	H	MRSH 		LS	00				N				UNTERESRIET	Unteres Riet	Unteres Riet	1993-12-22
+1	-1187189	-1749209	47.1333333	9.5166667	470800	93100	NT32	NL32-02	A	ADM1 		LS	00				N				VADUZ	Vaduz	Vaduz	1993-12-22
+1	-1187190	-1749210	47.1333333	9.5166667	470800	93100	NT32	NL32-02	P	PPLC 		LS	00				N				VADUZ	Vaduz	Vaduz	1995-04-26
+1	419571	535542	47.0833333	9.5833333	470500	93500	NT41	NL32-02	T	VAL		LS	00				N				VALUNA	Valüna	Valuna	1999-01-26
+1	-1187191	-1749211	47.2333333	9.5333333	471400	93200	NT43	NL32-02	P	PPLX 		LS	00				N				VORDERERSCHELLENBERG	Vorderer Schellenberg	Vorderer Schellenberg	1993-12-22
+1	-1187192	-1749212	47.0500000	9.5833333	470300	93500	NT41	NL32-02	T	PK		LS	00				N				VORDERGRAUSPITZ	Vorder-Grauspitz	Vorder-Grauspitz	1993-12-22
+1	419567	535537	47.1000000	9.5333333	470600	93200	NT41	NL32-02	P	PPL		LS	00				V				WANGERBARG	Wangerbärg	Wangerbarg	1999-01-26
+1	419567	535572	47.1000000	9.5333333	470600	93200	NT41	NL32-02	P	PPL		LS	00				N				WANGERBERG	Wangerberg	Wangerberg	1999-01-26

Added: packages/thuban/branches/upstream/current/Extensions/gns2shp/test/test_gns2shp.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/gns2shp/test/test_gns2shp.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/gns2shp/test/test_gns2shp.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,90 @@
+# Copyright (c) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test gns2shp extension.
+"""
+
+__version__ = "$Revision: 2484 $"
+# $Source$
+# $Id: test_gns2shp.py 2484 2004-12-18 22:40:45Z jan $
+
+import unittest
+import os
+import sys
+
+# If run directly as a script, add Thuban's test directory, the Lib
+# directory and the Thuban directory itself to the path.
+# Otherwise we assume that the importing code as already done it
+if __name__ == "__main__":
+    sys.path.append(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])),
+                                 "..", "..", "..", "test"))
+    sys.path.append(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])),
+                                 "..", "..", "..", "Lib"))
+    sys.path.append(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])),
+                                 "..", "..", ".."))
+
+import support
+import shapelib
+from dbflib import DBFFile, FTString, FTInteger, FTDouble
+from Extensions.gns2shp.gns2shp import gns2shp
+
+class gns2shpTest(unittest.TestCase, support.FileTestMixin):
+
+    def test(self):
+        """Test for correct creation of Shapefile from GNS text file format"""
+        eq = self.assertEquals
+
+        # create a temporary gns file (use liechtenstein as reference)
+        filename = self.temp_file_name('test.gns')
+        os.system('cp ls.txt %s' % filename)
+
+        # convert the reference gns file to  shapefile
+        dest_filename = self.temp_file_name('test')
+        n = gns2shp(filename, dest_filename)
+
+        # is the number of shapes correct?
+        eq(n, 88) # what gns2shp reports
+        # and now the actually written ones
+        shp = shapelib.ShapeFile(dest_filename)
+        numshapes, shapetype, mins, maxs = shp.info()
+        eq(numshapes, n)
+
+        # correct shapefile type?
+        eq(shapetype, shapelib.SHPT_POINT)
+
+        # attribute data correct?
+        field_types = { 'RC': FTInteger,
+                        'UFI': FTInteger,
+                        'UNI': FTInteger,
+                        'UTM': FTString,
+                        'JOG': FTString,
+                        'FC': FTString,
+                        'DSG': FTString,
+                        'PC': FTInteger,
+                        'CC1': FTString,
+                        'ADM1': FTString,
+                        'ADM2': FTString,
+                        'DIM': FTInteger,
+                        'CC2': FTString,
+                        'NT': FTString,
+                        'LC': FTString,
+                        'SHORT_FORM': FTString,
+                        'GENERIC': FTString,
+                        'SORT_NAME': FTString,
+                        'FULL_NAME': FTString,
+                        'FULL_ND': FTString,
+                        'MODIFY_DAT': FTString}
+        dbf = DBFFile(dest_filename)
+        eq(dbf.record_count(), n) # correct number of data sets?
+        eq(dbf.field_count(), len(field_types)) # correct number of fields?
+        for i in range(dbf.field_count()):
+            ftype, name, width, prec = dbf.field_info(i)
+            eq(ftype, field_types[name]) # field of correct type?
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/Extensions/importAPR/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/importAPR/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/importAPR/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,21 @@
+# Copyright (c) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+# import the actual module
+import importAPR
+
+# perform the registration of the extension
+from Thuban import _
+from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+
+ext_registry.add(ExtensionDesc(
+    name = 'importAPR',
+    version = '0.1.1',
+    authors= [ 'Jan-Oliver Wagner' ],
+    copyright = '2003, 2004 Intevation GmbH',
+    desc = _("Import a ArcView project file (.apr)\n" \
+             "and convert it to Thuban.")))

Added: packages/thuban/branches/upstream/current/Extensions/importAPR/apr.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/importAPR/apr.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/importAPR/apr.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,225 @@
+# Copyright (C) 2003-2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Classes for ArcView Objects as in '.apr'-files.
+
+The classes are only added to this module if they
+are considered to be complete and whenever possible
+accompanied by unit tests (see tests/).
+Experimental classes should remain in importAPR.py.
+"""
+
+__version__ = "$Revision: 2629 $"
+
+from math import ceil
+
+from Thuban.Model.color import Color, Transparent, Black
+from Thuban.Model.range import Range
+from Thuban.Model.classification import ClassGroupProperties
+
+from odb import ODBBaseObject
+
+class APR_BLnSym(ODBBaseObject):
+    """Line symbol object.
+    Always references a color object TClr via 'Color'.
+
+    The stroke width 'Width' is always given, but the scale is
+    unclear so far (e.g. which width is actually meant with value '0.1'?).
+    Meanwhile, the ceiling of 'Width' is applied to be stroke width
+    in pixels.
+
+    Finally, there seems always to be a 'Pattern'-List consisting of
+    float values. No idea so far, how to interpret this (Thuban does
+    not support pattern yet anyway).
+    """
+    _obj_refs = [ 'Color' ]
+    _values = [ 'Width', 'Pattern' ]
+
+    def GetThubanProp(self):
+        """Create a Thuban ClassGroupProperty from this object and
+        return it.
+        """
+        prop = ClassGroupProperties()
+        prop.SetLineColor(self.Get('Color').GetThubanColor())
+        prop.SetLineWidth(int(ceil(float(self.Get('Width')))))
+        return prop
+
+class APR_BMkSym(ODBBaseObject):
+    """Point symbol object.
+    Always references a Color and a Background Color via 'Color', 'BgColor'.
+    For Thuban, Color is interpreted as line color and BGColor is
+    interpreted as fill color.
+
+    Next, there is always a 'Font' reference. Probably this defines
+    the font for the label. This is not interpreted for Thuban.
+
+    There is always a Size element. It is not clear how 'size'
+    defined in ArcView.
+
+    There is always a Angle element, but I don't know how this is
+    defined. I only sighted the value of 360 so far.
+
+
+    Finally, there seems always to be a 'Pattern'-List consisting of
+    float values. No idea so far, how to interpret this (Thuban does
+    not support pattern yet anyway).
+    """
+
+    _obj_refs = [ 'Color', 'BgColor', 'Font' ]
+    _values = [ 'Angle', 'Size', 'Pattern' ]
+
+    def GetThubanProp(self):
+        """Create a Thuban ClassGroupProperty from this object and
+        return it.
+
+        In Thuban, the points have all the same size,
+        but we can vary the width of the line.
+        """
+        prop = ClassGroupProperties()
+        prop.SetSize(int(ceil(float(self.Get('Size')))))
+        prop.SetLineColor(self.Get('Color').GetThubanColor())
+        prop.SetFill(self.Get('BgColor').GetThubanColor())
+        return prop
+
+class APR_BShSym(ODBBaseObject):
+    """Polygon symbol object, either filled with a single color or
+    with a pattern.
+    .
+    Always references TClr objects via 'Color', 'OutlineColor' and 'BgColor'.
+    Always has attributes 'OutlineWidth' and 'Outline'.
+
+    OutlineColor is interpreted to be the Thuban line color, OutlineWidth
+    as the Thuban line width.
+    'Color' is interpreted to be the Thuban fill color.
+    'BgColor' is not interpreted and probably has something to do with
+    patterns (Stripple).
+    'Stripple' ist not interpreted in Thuban. It is a pattern definition
+    based on a bitpattern. Thuban has no Patterns yet.
+
+    It is unclear what 'Outline' defines and thus is not used for Tuban.
+    """
+    _obj_refs = [ 'Color', 'OutlineColor', 'BgColor', 'Stripple' ]
+    _values = [ 'OutlineWidth', 'Outline' ]
+
+    def GetThubanProp(self):
+        """Create a Thuban ClassGroupProperty from this object and
+        return it.
+        """
+        prop = ClassGroupProperties()
+        prop.SetLineWidth(int(ceil(float(self.Get('OutlineWidth')))))
+        prop.SetLineColor(self.Get('OutlineColor').GetThubanColor())
+        prop.SetFill(self.Get('Color').GetThubanColor())
+        return prop
+
+class APR_LClass(ODBBaseObject):
+    """This object describes the range and label of a class
+    within a legend.
+
+    'IsText' determines whether 'MinStr'/'MaxStr' are given, else
+    'MinNum'/'MaxNum' should be there.
+    So far, only String-Ranges with identical 'MinStr'/'MaxStr' have
+    been sighted.
+
+    'MinNum' may not be there. In this case assume it to be -oo.
+
+    There are objects with 'IsNoData' set to 1. Not yet sure how to
+    treat them.
+
+    However, objects have been sighted that only have 'IsText' and
+    'Precision': We assume an empty label and a full range.
+
+    No referenced objects.
+    """
+    _obj_refs = [ ]
+    _values = [ 'IsText', 'MinStr', 'MaxStr', 'MinNum', 'MaxNum', 'Label',
+                'Precision', 'IsNoData' ]
+
+    def GetThubanRange(self):
+        """Return a Thuban range that corresponds to this object.
+
+        The returned object is a
+        - Range-Object in case of a numerical range.
+        - String-Object in case of a text range (assuming that
+          text objects occur only with 'MinStr' == 'MaxStr'.
+        """
+        if hasattr(self, 'IsText'):
+            if hasattr(self, 'MinStr'):
+                return self.MinStr
+            else:
+                return ''
+
+        # build range
+        if hasattr(self, 'MinNum'):
+            range_str = ']' + self.MinNum + ';'
+        else:
+            range_str = ']-oo;'
+        if hasattr(self, 'MaxNum'):
+            range_str = range_str + self.MaxNum + ']'
+        else:
+            range_str = None
+
+        if hasattr(self, 'MinNum') and hasattr(self, 'MaxNum'):
+            if self.MinNum == self.MaxNum:
+                range_str = '[' + self.MinNum + ';' + self.MaxNum + ']'
+        return Range(range_str)
+
+    def GetLabel(self):
+        """Return the label string.
+        Return an  empty string if there is no 'Label'.
+        """
+        if hasattr(self, 'Label'):
+            return self.Label
+        else:
+            return ''
+
+
+class APR_TClr(ODBBaseObject):
+    """Color object. Appears in 3 styles:
+    1. no attributes: (so far assumed as black)
+    2. only 'Name': a string that describes the color.
+       Seen only "Transparent".
+    3. 'Red', 'Green', 'Blue': RGB code. Each value in '0xffff' style.
+       3.1 Only one or two of the colors are defined. It is assumed
+           that in this case the rest is equal to 0x0000
+       3.2 Some hex-codes are incomplete (eg. 0xff). It is assumed
+           that the missing digits are "0".
+
+    No referenced objects.
+    """
+    _obj_refs = [ ]
+    _values = [ 'Name', 'Red', 'Green', 'Blue' ]
+
+    def GetThubanColor(self):
+        """Return a Thuban Color object; returns None if a problem
+        occured.
+        """
+        if hasattr(self, 'Red') or hasattr(self, 'Green') or \
+            hasattr(self, 'Blue'):
+            rgb = { 'Red': 0, 'Green': 0, 'Blue': 0 } # default for missing
+                                                      # parts: 0x0000
+
+            for color in [ 'Red', 'Green', 'Blue' ]:
+                if hasattr(self, color):
+                    s = getattr(self, color)
+                    # It seems that ArcView sometimes uses only
+                    # 2 bytes for a color definition, eg. 0xff.
+                    # It is assumed that this is the same as
+                    # 0x00ff (and not the same as 0xff00). At
+                    # least color comparison shows this.
+                    # Thus we do not need to append "00" if length
+                    # of s is < 6. The following conversion does is
+                    # right even for the short strings.
+                    rgb[color] = int(s, 16)/float(int('0xffff', 16))
+            return Color(rgb['Red'], rgb['Green'], rgb['Blue'])
+        elif hasattr(self, 'Name'):
+            if self.Name == 'Transparent':
+                return Transparent
+            else:
+                return None
+        else:
+            return Black

Added: packages/thuban/branches/upstream/current/Extensions/importAPR/importAPR.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/importAPR/importAPR.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/importAPR/importAPR.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,338 @@
+# Copyright (C) 2003-2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Import a ArcView project file (.apr) and convert it
+to Thuban.
+"""
+
+__version__ = "$Revision: 2721 $"
+# $Source$
+# $Id: importAPR.py 2721 2007-01-13 15:11:42Z dpinte $
+
+import os, sys
+
+from types import StringType
+
+import wx
+
+from Thuban.Model.extension import Extension
+from Thuban.Model.base import TitledObject, Modifiable
+from Thuban.UI.command import registry, Command
+from Thuban.UI.mainwindow import main_menu
+from Thuban import _
+from Thuban.Model.layer import Layer
+from Thuban.Model.classification import ClassGroupRange, ClassGroupSingleton
+
+from odb import ODBBaseObject
+from apr import APR_LClass, APR_TClr, APR_BLnSym, APR_BMkSym, APR_BShSym
+
+class ODBExtension(Extension):
+    def TreeInfo(self):
+        return (_("Extension: %s") % self.title,
+                [ object.TreeInfo() for object in self.objects ])
+
+class APR_FTheme(ODBBaseObject):
+    _obj_refs = [ 'Source', 'Legend' ]
+
+class APR_Legend(ODBBaseObject):
+    """Legend object.
+    There could one or more Class objects. Each class corresponds to a
+    Child in the Symbols.
+    """
+    _obj_refs = [ 'FieldNames', 'Symbols', 'Class', 'NullSym',
+                  'NullValues', 'StatValues' ]
+
+class APR_VShSym(ODBBaseObject):
+    """Pattern Object(Symbol).
+    """
+    _obj_refs = [ 'Color', 'OutlineColor', 'BgColor' ]
+    _values = [ 'Outline', 'Outlinewidth', 'Angle', 'YSeparation',
+                'PenSize' ]
+
+class APR_Project(ODBBaseObject):
+    _obj_refs = [ 'Doc' ]
+
+class APR_ShpSrc(ODBBaseObject):
+    _obj_refs = [ 'Name' ]
+
+class APR_SrcName(ODBBaseObject):
+    _obj_refs = [ 'FileName' ]
+
+class APR_SymList(ODBBaseObject):
+    _obj_refs = [ 'Child' ]
+
+class APR_View(ODBBaseObject):
+    _obj_refs = [ 'Theme', 'ITheme' ]
+
+class ODB(TitledObject, Modifiable):
+
+    def __init__(self):
+        TitledObject.__init__(self, 'ODB Object')
+        self._objects = {}
+        self._version = None
+        self._filename = None
+        self.name = None # required for Thuban.model.extension.Extension
+
+    def SetFileName(self, fname):
+        self._filename = fname
+        self.name = fname
+
+    def AddObject(self, object):
+        self._objects[object.number] = object
+
+    def GetObjects(self):
+        return self._objects
+
+    def GetProject(self):
+        """Return the main Root if it is a Project, else None."""
+        # it is assumed that the first object is the ODB object
+        if self._objects[1].type != 'ODB':
+            return None
+        if self._objects[1].FirstRootClassName != 'Project':
+            return None
+
+        # it is assumed that the second object is the first root
+        o = self._objects[2]
+        if o.type != 'Project':
+            return None
+        return o
+
+    def TreeInfo(self):
+        items = []
+        items.append(_('Format version: %s') % self._version)
+        p = self.GetProject()
+        items.append(_('Project Name: %s') % p.Name)
+        for doc in p.Get('Doc'):
+            items.append(doc.TreeInfo())
+        return [_("ODB File '%s'" % self._filename), items]
+
+def parse_apr(fname):
+    """Load a ArcView project file.
+
+    fname  -- Filename of the .apr file
+
+    Return: the ODB class object.
+    """
+    odb = ODB()
+    odb.SetFileName(fname)
+
+    apr = open(fname, 'r').readlines()
+
+    # get the version from the first line (eg. from "/3.1")
+    odb._version = apr.pop(0)[1:]
+
+    i = 0
+    in_object = False
+    for line in apr:
+        i += 1
+        if line[0] == '(':
+            line = line[1:]
+            type, number = line.split('.')
+            number = int(number)
+            class_name = 'APR_' + type
+            try:
+                clazz = eval(class_name)
+                object = clazz(odb, type, number)
+            except:
+                object = ODBBaseObject(odb, type, number)
+            in_object = True
+            continue
+        if line[0] == ')':
+            in_object = False
+            odb.AddObject(object)
+        if in_object:
+            line = line.strip()
+            if len(line) == 0: continue
+            try:
+                property, value = line.split(':', 1)
+                property = property.strip()
+                value = value.strip()
+            except:
+                print "Error in line %d:" % i, line
+                continue
+            if value[0] == '"':
+                value = value[1:-1]
+            setattr(object, property, value)
+    return odb
+
+def import_apr_dialog(context):
+    """Request filename from user and run importing of apr file.
+
+    context -- The Thuban context.
+    """
+    dlg = wx.FileDialog(context.mainwindow,
+                       _("Select APR file"), ".", "",
+                       _("ArcView Project Files (*.apr)|*.apr|") +
+                       _("All Files (*.*)|*.*"),
+                       wx.OPEN|wx.OVERWRITE_PROMPT)
+    if dlg.ShowModal() == wx.ID_OK:
+        filename = dlg.GetPath()
+        dlg.Destroy()
+    else:
+        return
+
+    odb = parse_apr(filename)
+    if odb is None:
+        context.mainwindow.RunMessageBox(_("Import APR"), _("Loading failed"))
+        return
+    else:
+        context.mainwindow.RunMessageBox(_("Import APR"),
+                                         _("%d objects loaded" % 
+                                            len(odb.GetObjects().keys())))
+
+    # find the views of the APR file
+    views = {}
+    p = odb.GetProject()
+    for doc in p.Get('Doc'):
+        if doc.type != 'View':
+            continue
+        views[doc.Name] = doc
+
+    # it is possible that a APR file has no view at all
+    if len(views) == 0:
+        context.mainwindow.RunMessageBox(_("Import APR"),
+                _("No view found in APR file"))
+        return
+
+    # let the user select one of the views
+    if len(views) > 1:
+        titles = views.keys()
+        dlg = wx.SingleChoiceDialog(context.mainwindow,
+                                   _('Pick a View to import:'),
+                                   _('Import APR'), titles,
+                                   style = wx.DEFAULT_DIALOG_STYLE | 
+                                           wx.RESIZE_BORDER)
+        if dlg.ShowModal() == wx.ID_OK:
+            view = views[views.keys()[dlg.GetSelection()]]
+        else:
+            return
+    else:
+        view = views[views.keys()[0]]
+
+    # load the themes of the View as layers into Thuban
+    count_theme = 0
+    count_theme_fail = 0
+    for theme in view.Get('Theme'):
+        if theme.type !=  'FTheme':
+            continue
+        count_theme += 1
+        filename = theme.Get('Source').Get('Name').Get('FileName').Path
+        try:
+            store = context.application.Session().OpenShapefile(filename)
+        except IOError:
+            # the layer couldn't be opened
+            context.mainwindow.RunMessageBox(_('Add Layer'),
+                           _("Can't open the file '%s'.") % filename)
+            count_theme_fail += 1
+        else:
+            title = theme.Name
+            apr_legend = theme.Get('Legend')
+
+            map = context.mainwindow.canvas.Map()
+
+            # create layer
+            layer = Layer(title, store)
+
+            # set the field for classification (if there is one in the apr)
+            if hasattr(apr_legend, 'FieldNames'):
+                apr_fieldname = apr_legend.Get('FieldNames').S
+                # unfortunately, the APR file does not store the actual
+                # Name of the column, but always makes the first character
+                # a capital letter, the rest lower case.
+                # Therefore, we have to search through the table of the
+                # layer to find out the correct spelling.
+                table_columns = layer.ShapeStore().Table().Columns()
+                for column in table_columns:
+                    if apr_fieldname.lower() == column.name.lower():
+                        layer.SetClassificationColumn(column.name)
+                        break
+
+            clazz = layer.GetClassification()
+            apr_classes = apr_legend.Get('Class')
+            if not isinstance(apr_classes, list):
+                apr_classes = [ apr_classes ]
+            apr_symbols = apr_legend.Get('Symbols').Get('Child')
+            if not isinstance(apr_symbols, list):
+                apr_symbols = [ apr_symbols ]
+            i = -1
+            for symbol in apr_symbols:
+                i += 1
+
+                if hasattr(apr_classes[i], 'IsNoData'):
+                    group = clazz.GetDefaultGroup()
+                    group.SetLabel(apr_classes[i].Label)
+                    continue
+
+                # create a new group property from the symbol
+                prop = symbol.GetThubanProp()
+
+                # build range
+                range = apr_classes[i].GetThubanRange()
+
+                if isinstance(range, StringType):
+                    new_group = ClassGroupSingleton(value = range,
+                                    props = prop,
+                                    label = apr_classes[i].GetLabel())
+                else:
+                    new_group = ClassGroupRange(_range = range,
+                                    props = prop,
+                                    label = apr_classes[i].GetLabel())
+                clazz.AppendGroup(new_group)
+
+            map.AddLayer(layer)
+
+    map.SetTitle(view.Name)
+
+    # fit the new map to the window
+    context.mainwindow.canvas.FitMapToWindow()
+
+    context.mainwindow.RunMessageBox(_('Import APR'),
+        _('Imported %d out of %d themes of view "%s" ...') % \
+            (count_theme - count_theme_fail, count_theme, view.Name))
+
+    # import_apr as an extension to Thuban
+    if context.session.HasExtensions():
+        for ext in context.session.Extensions():
+            if ext.Title() == apr_import_extension.Title():
+                ext.AddObject(odb)
+                return
+
+    # no extension found, so lets make a new
+    context.session.AddExtension(apr_import_extension)
+    apr_import_extension.AddObject(odb)
+
+if __name__ == "__main__": # import_apr executed as a command line tool
+    if len(sys.argv) == 2:
+        odb = parse_apr(sys.argv[1])
+        print "%d objects loaded" % len(odb.GetObjects().keys())
+
+        def print_structured_list(lst, indent = ''):
+            for item in lst:
+                if isinstance(item, StringType):
+                    print indent + item
+                elif isinstance(item, list):
+                    print_structured_list(item, indent + ' ')
+
+        print_structured_list(odb.TreeInfo())
+        sys.exit(0)
+    else:
+        print 'usage: %s apr-file' % sys.argv[0]
+        sys.exit(1)
+
+apr_import_extension = ODBExtension('APR Import')
+
+# register the new command
+registry.Add(Command('import-apr', _('Import apr-file...'), import_apr_dialog,
+                         helptext = _('Import a ArcView project file')))
+
+# find the experimental menu (create it anew if not found)
+experimental_menu = main_menu.FindOrInsertMenu('experimental',
+                                               _('Experimenta&l'))
+
+# finally add the new entry to the experimental menu
+experimental_menu.InsertItem('import-apr')

Added: packages/thuban/branches/upstream/current/Extensions/importAPR/odb.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/importAPR/odb.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/importAPR/odb.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,131 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Classes for generic ArcView ODB Objects
+as in '.apr', '.avl' and other files.
+"""
+
+__version__ = "$Revision: 1882 $"
+
+from types import StringType
+
+from Thuban import _
+
+class ODBBaseObject:
+
+    """Base class for ODB objects."""
+
+    _obj_refs = [] # override this list with the object names
+                   # as strings that are referenced.
+    _values = []   # override this list with the keywords
+                   # for known values of the class.
+
+    def __init__(self, parent_odb, type, number):
+        self._parent_odb = parent_odb
+        self.type = type
+        self.number = number
+
+    def __setattr__(self, attr, value):
+        """If an attribute is set that already exists,
+        a list is created to contain both. Any further
+        attribute with the same name is appended to the list.
+        """
+        if hasattr(self, attr):
+            v = getattr(self, attr)
+            if isinstance(v, list):
+                v.append(value)
+            else:
+                self.__dict__[attr] = [v, value]
+        else:
+            self.__dict__[attr] = value
+
+    def __repr__(self):
+        """The string represenation of an object is the syntax
+        as used in the ODB file.
+        """
+        s = '(' + self.type + '.' + str(self.number) + '\n'
+        for k in self.__dict__.keys():
+            if k in [ '_parent_odb', 'type', 'number']: continue
+            v = self.__dict__[k]
+            if isinstance(v, list):
+                for val in v:
+                    s += "\t%s:\t%s\n" % (k, val)
+            else:
+                s += "\t%s:\t%s\n" % (k, v)
+        s += ')\n'
+        return s
+
+    def Get(self, attr):
+        """If an attribute is a pointer (or a list of pointers)
+        to another object (other objects), references are resolved
+        to point to the corresponding objects.
+
+        attr -- string with the name of the attribute
+        """
+        if not hasattr(self, attr):
+            print "Object %s.%s has no attribute %s!" % ( self.type,
+                    self.number, attr)
+            return None
+
+        if attr in self._obj_refs:
+            if isinstance(self.__dict__[attr], list): 
+                lst = []
+                for obj_id in self.__dict__[attr]:
+                    obj_id = int(obj_id)
+                    if not self._parent_odb.GetObjects().has_key(obj_id):
+                        print "Object #%d missing!" % obj_id
+                    else:
+                        lst.append(self._parent_odb.GetObjects()[obj_id])
+                return lst
+            else:
+                obj_id = int(self.__dict__[attr])
+                if not self._parent_odb.GetObjects().has_key(obj_id):
+                    print "Object #%d missing!" % s
+                    return None
+                return self._parent_odb.GetObjects()[obj_id]
+
+        return self.__dict__[attr]
+
+    def TreeInfo(self):
+        """Return the information in a tree-like structure."""
+        items = []
+
+        # known values
+        for o in self._values:
+            if hasattr(self, o):
+                items.append('%s: %s' % (o, self.Get(o)))
+
+        # the objects
+        for o in self._obj_refs:
+            if not hasattr(self, o): continue
+            if not isinstance(self.Get(o), list):
+                items.append(self.Get(o).TreeInfo())
+                # add the variable name of the object:
+                items[-1][0] = '%s: %s' % (o, items[-1][0])
+                continue
+            for obj in self.Get(o):
+                items.append(obj.TreeInfo())
+                # add the variable name of the object:
+                items[-1][0] = '%s: %s' % (o, items[-1][0])
+
+        # unknown values
+        for k in self.__dict__.keys():
+            if k in [ '_parent_odb', 'type', 'number']: continue
+            if k in self._obj_refs: continue
+            if k in self._values: continue
+            v = self.__dict__[k]
+            if isinstance(v, list):
+                items.append(_("Unknown Object list named: '%s'") % k)
+            else:
+                if isinstance(v, StringType):
+                    items.append(_("Unknown Value named: '%s' with value '%s'")\
+                        % ( k, v ))
+                else:
+                    items.append(_('Unknown Object named: %s') % k)
+
+        return [self.type, items]

Added: packages/thuban/branches/upstream/current/Extensions/importAPR/samples/README
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/importAPR/samples/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/importAPR/samples/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,5 @@
+Howto view the sample apr-files:
+
+iceland.apr: start Thuban from the main CVS thuban directory.
+             (the paths to the Iceland datafiles are relative
+             and will work then)

Added: packages/thuban/branches/upstream/current/Extensions/importAPR/samples/iceland.apr
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/importAPR/samples/iceland.apr	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/importAPR/samples/iceland.apr	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,4307 @@
+/3.1
+(ODB.1
+	FirstRootClassName:	"Project"
+	Roots:	2
+	Version:	32
+)
+
+(Project.2
+	Name:	"iceland.apr"
+	CreationDate:	"Montag, 15. September 2003 10:16:20"
+	GUIName:	"Project"
+	Win:	3
+	CSMgr:	4
+	DocExts:	5
+	VisGUIWidth:	90
+	Doc:	6
+	Doc:	195
+	Buttons:	611
+	Buttons:	612
+	Buttons:	613
+	Scripts:	614
+	Prefs:	615
+	WorkDir:	1461
+	WinX:	-4
+	WinY:	-3
+	WinW:	1032
+	WinH:	747
+	SerialNumber:	"42"
+	SelColor:	1462
+	GUINames:	1463
+	GUINames:	1464
+	GUINames:	1465
+	GUINames:	1466
+	GUINames:	1467
+	GUINames:	1468
+	GUINames:	1469
+	TocWidthScale:	1.00000000000000
+)
+
+(DocWin.3
+	Owner:	2
+	Open:	1
+	X:	-4
+	Y:	-4
+	W:	1034
+	H:	643
+)
+
+(CSMgr.4
+)
+
+(DocAct.5
+	Doc:	2
+)
+
+(View.6
+	Name:	"Political Map of Iceland with Cultural Landmarks and Roads"
+	Creator:	"Test A. Little"
+	CreationDate:	"Montag, 15. September 2003 10:16:31"
+	GUIName:	"View"
+	Win:	7
+	CSMgr:	8
+	DocExts:	10
+	DocExts:	11
+	Graphics:	12
+	Theme:	19
+	Theme:	68
+	Theme:	154
+	LastScale:	4619242.64638806320000
+	Dpy:	13
+	TOCWidth:	150
+	CoordPrecision:	2
+)
+
+(DocWin.7
+	Owner:	6
+	X:	-4
+	Y:	-4
+	W:	1034
+	H:	643
+)
+
+(CSMgr.8
+	Client:	9
+)
+
+(CSClient.9
+	Client:	10
+	ReqName:	"ClientNfy"
+)
+
+(PanMgr.10
+	Doc:	6
+)
+
+(DocAct.11
+	Doc:	6
+)
+
+(GList.12
+	Dpy:	13
+	FormatNumb:	18
+)
+
+(MapDpy.13
+	Left:	-22.93289795163312
+	Bottom:	63.31776466852502
+	Top:	66.57350349909144
+	Right:	-13.38145151379742
+	ReportUnits:	4
+	Units:	10
+	Scale:	14
+	FrameTop:	6.37500000000000
+	FrameRight:	9.05208333333333
+	PageDpy:	15
+	FitToPage:	1
+	MouseLoc:	17
+)
+
+(Numb.14
+	N:	0.94771858819998
+)
+
+(PageDpy.15
+	Top:	6.37500000000000
+	Right:	9.05208333333333
+	ReportUnits:	1
+	Units:	1
+	Scale:	16
+	ZoomRight:	9.05208333333333
+	ZoomTop:	6.37500000000000
+	GridSpacingX:	0.25000000000000
+	GridSpacingY:	0.25000000000000
+)
+
+(Numb.16
+	N:	0.11047180667434
+)
+
+(PointD.17
+	x:	-13.40343412930452
+	y:	68.25401771762704
+)
+
+(Numb.18
+)
+
+(FTheme.19
+	Name:	"Roads"
+	Source:	20
+	Flags:	0x06
+	Legend:	37
+	Threshold:	56
+	View:	6
+	GSet:	57
+	LegEditScript:	"View.EditLegend"
+	TxPos:	58
+	AttrRules:	59
+	AttrRules:	60
+	AttrRules:	61
+	AttrRules:	62
+	AttrRules:	63
+	AttrRules:	64
+	AttrRules:	65
+	AttrRules:	66
+	AttrRules:	67
+	SnapTolCursor:	1
+)
+
+(ShpSrc.20
+	Name:	21
+	FTab:	23
+)
+
+(SrcName.21
+	FileName:	22
+	Name:	"roads-line.shp"
+	SubName:	"Arc"
+	OwnerClass:	"ShpSrc"
+)
+
+(FN.22
+	Path:	"Data/iceland/roads-line.shp"
+)
+
+(FTab.23
+	Name:	"roads-line.dbf"
+	BTab:	24
+	Fields:	35
+	Fields:	25
+	Fields:	26
+	Fields:	27
+	Fields:	28
+	Fields:	29
+	Fields:	30
+	Fields:	31
+	Fields:	32
+	Fields:	33
+	SelBits:	36
+	FSrc:	20
+)
+
+(dBASE.24
+	Name:	"roads-line.dbf"
+	Fields:	25
+	Fields:	26
+	Fields:	27
+	Fields:	28
+	Fields:	29
+	Fields:	30
+	Fields:	31
+	Fields:	32
+	Fields:	33
+	FileName:	34
+)
+
+(Field.25
+	Name:	"Fnode_"
+	Btab:	24
+	Alias:	"Fnode_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.26
+	Name:	"Tnode_"
+	Btab:	24
+	Alias:	"Tnode_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.27
+	Name:	"Lpoly_"
+	Btab:	24
+	Alias:	"Lpoly_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.28
+	Name:	"Rpoly_"
+	Btab:	24
+	Alias:	"Rpoly_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.29
+	Name:	"Length"
+	Btab:	24
+	Alias:	"Length"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.30
+	Name:	"Rdline_"
+	Btab:	24
+	Alias:	"Rdline_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.31
+	Name:	"Rdline_id"
+	Btab:	24
+	Alias:	"Rdline_id"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.32
+	Name:	"Rdlntype"
+	Btab:	24
+	Alias:	"Rdlntype"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.33
+	Name:	"Rdlnstat"
+	Btab:	24
+	Alias:	"Rdlnstat"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(FN.34
+	Path:	"Data/iceland/roads-line.dbf"
+)
+
+(Field.35
+	Name:	"Shape"
+	Alias:	"Shape"
+	Visible:	1
+	Type:	18
+	Order:	-1
+)
+
+(Bitmap.36
+	NumBits:	839
+
+)
+
+(Legend.37
+	SymType:	0x01
+	LegType:	0x02
+	ClassType:	0x03
+	FieldNames:	38
+	Symbols:	39
+	Class:	48
+	Class:	49
+	Class:	50
+	Class:	51
+	StdDevs:	1.00000000000000
+	NullSym:	52
+	NullValues:	54
+	StatValues:	55
+	Precision:	-3
+)
+
+(AVStr.38
+	S:	"Rdlntype"
+)
+
+(SymList.39
+	Child:	40
+	Child:	42
+	Child:	44
+	Child:	46
+)
+
+(BLnSym.40
+	Color:	41
+	Width:	0.10000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+)
+
+(TClr.41
+)
+
+(BLnSym.42
+	Color:	43
+	Width:	0.10000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+)
+
+(TClr.43
+	Red:	0xa5a5
+	Green:	0xa5a5
+	Blue:	0xa5a5
+)
+
+(BLnSym.44
+	Color:	45
+	Width:	0.10000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+)
+
+(TClr.45
+	Red:	0xffff
+	Green:	0xffff
+	Blue:	0xffff
+)
+
+(BLnSym.46
+	Color:	47
+	Width:	0.10000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+)
+
+(TClr.47
+	Name:	"Transparent"
+)
+
+(LClass.48
+	Label:	"1"
+	MinNum:	2.00000000000000
+	MaxNum:	2.00000000000000
+	Precision:	-3
+)
+
+(LClass.49
+	Label:	"2"
+	MinNum:	3.00000000000000
+	MaxNum:	3.00000000000000
+	Precision:	-3
+)
+
+(LClass.50
+	Label:	"3"
+	MinNum:	4.00000000000000
+	MaxNum:	8.00000000000000
+	Precision:	-3
+)
+
+(LClass.51
+	IsNoData:	1
+	Label:	"Keine Daten"
+	MaxNum:	-1.00000000000000
+	Precision:	-3
+)
+
+(BLnSym.52
+	Color:	53
+	Width:	0.10000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+)
+
+(TClr.53
+	Name:	"Transparent"
+)
+
+(NameDict.54
+)
+
+(NameDict.55
+)
+
+(Thresh.56
+)
+
+(GSet.57
+)
+
+(TxPosArc.58
+	HAlign:	3
+	VAlign:	1
+)
+
+(AttrSingle.59
+	FTab:	23
+	Field:	25
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.60
+	FTab:	23
+	Field:	26
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.61
+	FTab:	23
+	Field:	27
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.62
+	FTab:	23
+	Field:	28
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.63
+	FTab:	23
+	Field:	29
+	UnionRule:	6
+	SplitRule:	4
+)
+
+(AttrSingle.64
+	FTab:	23
+	Field:	30
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.65
+	FTab:	23
+	Field:	31
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.66
+	FTab:	23
+	Field:	32
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.67
+	FTab:	23
+	Field:	33
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(FTheme.68
+	Name:	"Cultural Landmarks"
+	Source:	69
+	Flags:	0x06
+	Legend:	83
+	Threshold:	151
+	View:	6
+	GSet:	152
+	LegEditScript:	"View.EditLegend"
+	TxPos:	153
+	LabelField:	78
+	SnapTolCursor:	1
+)
+
+(ShpSrc.69
+	Name:	70
+	FTab:	72
+)
+
+(SrcName.70
+	FileName:	71
+	Name:	"cultural_landmark-point.shp"
+	SubName:	"Point"
+	OwnerClass:	"ShpSrc"
+)
+
+(FN.71
+	Path:	"Data/iceland/cultural_landmark-point.shp"
+)
+
+(FTab.72
+	Name:	"cultural_landmark-point.dbf"
+	BTab:	73
+	Fields:	81
+	Fields:	74
+	Fields:	75
+	Fields:	76
+	Fields:	77
+	Fields:	78
+	Fields:	79
+	SelBits:	82
+	FSrc:	69
+)
+
+(dBASE.73
+	Name:	"cultural_landmark-point.dbf"
+	Fields:	74
+	Fields:	75
+	Fields:	76
+	Fields:	77
+	Fields:	78
+	Fields:	79
+	FileName:	80
+)
+
+(Field.74
+	Name:	"Area"
+	Btab:	73
+	Alias:	"Area"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.75
+	Name:	"Perimeter"
+	Btab:	73
+	Alias:	"Perimeter"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.76
+	Name:	"Clpoint_"
+	Btab:	73
+	Alias:	"Clpoint_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.77
+	Name:	"Clpoint_id"
+	Btab:	73
+	Alias:	"Clpoint_id"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.78
+	Name:	"Clptlabel"
+	Btab:	73
+	Alias:	"Clptlabel"
+	Visible:	1
+	Type:	4
+	Order:	-1
+)
+
+(Field.79
+	Name:	"Clptflag"
+	Btab:	73
+	Alias:	"Clptflag"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(FN.80
+	Path:	"Data/iceland/cultural_landmark-point.dbf"
+)
+
+(Field.81
+	Name:	"Shape"
+	Alias:	"Shape"
+	Visible:	1
+	Type:	17
+	Order:	-1
+)
+
+(Bitmap.82
+	NumBits:	34
+
+)
+
+(Legend.83
+	LegType:	0x08
+	ClassType:	0x03
+	FieldNames:	84
+	Symbols:	85
+	Class:	135
+	Class:	136
+	Class:	137
+	Class:	138
+	Class:	139
+	Class:	140
+	Class:	141
+	StdDevs:	1.00000000000000
+	NullSym:	142
+	NullValues:	149
+	StatValues:	150
+	Precision:	-3
+)
+
+(AVStr.84
+	S:	"Clptlabel"
+)
+
+(SymList.85
+	Child:	86
+	Child:	93
+	Child:	100
+	Child:	107
+	Child:	114
+	Child:	121
+	Child:	128
+)
+
+(BMkSym.86
+	Color:	87
+	BgColor:	88
+	Font:	89
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.87
+	Red:	0xffff
+)
+
+(TClr.88
+	Name:	"Transparent"
+)
+
+(NFont.89
+	Family:	90
+	Name:	91
+	Style:	92
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.90
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.91
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.92
+	S:	"Normal"
+)
+
+(BMkSym.93
+	Color:	94
+	BgColor:	95
+	Font:	96
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.94
+	Red:	0xa100
+	Green:	0x6686
+	Blue:	0x32f0
+)
+
+(TClr.95
+	Name:	"Transparent"
+)
+
+(NFont.96
+	Family:	97
+	Name:	98
+	Style:	99
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.97
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.98
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.99
+	S:	"Normal"
+)
+
+(BMkSym.100
+	Color:	101
+	BgColor:	102
+	Font:	103
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.101
+	Red:	0xd9d
+	Green:	0x81
+	Blue:	0x8200
+)
+
+(TClr.102
+	Name:	"Transparent"
+)
+
+(NFont.103
+	Family:	104
+	Name:	105
+	Style:	106
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.104
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.105
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.106
+	S:	"Normal"
+)
+
+(BMkSym.107
+	Color:	108
+	BgColor:	109
+	Font:	110
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.108
+	Red:	0xffff
+	Green:	0xffff
+)
+
+(TClr.109
+	Name:	"Transparent"
+)
+
+(NFont.110
+	Family:	111
+	Name:	112
+	Style:	113
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.111
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.112
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.113
+	S:	"Normal"
+)
+
+(BMkSym.114
+	Color:	115
+	BgColor:	116
+	Font:	117
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.115
+	Red:	0xffff
+	Green:	0xffff
+	Blue:	0xffff
+)
+
+(TClr.116
+	Name:	"Transparent"
+)
+
+(NFont.117
+	Family:	118
+	Name:	119
+	Style:	120
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.118
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.119
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.120
+	S:	"Normal"
+)
+
+(BMkSym.121
+	Color:	122
+	BgColor:	123
+	Font:	124
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.122
+)
+
+(TClr.123
+	Name:	"Transparent"
+)
+
+(NFont.124
+	Family:	125
+	Name:	126
+	Style:	127
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.125
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.126
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.127
+	S:	"Normal"
+)
+
+(BMkSym.128
+	Color:	129
+	BgColor:	130
+	Font:	131
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.129
+	Name:	"Transparent"
+)
+
+(TClr.130
+	Name:	"Transparent"
+)
+
+(NFont.131
+	Family:	132
+	Name:	133
+	Style:	134
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.132
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.133
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.134
+	S:	"Normal"
+)
+
+(LClass.135
+	IsText:	1
+	Label:	"BUILDING"
+	MinStr:	"BUILDING"
+	MaxStr:	"BUILDING"
+	Precision:	-3
+)
+
+(LClass.136
+	IsText:	1
+	Label:	"FARM"
+	MinStr:	"FARM"
+	MaxStr:	"FARM"
+	Precision:	-3
+)
+
+(LClass.137
+	IsText:	1
+	Label:	"HUT"
+	MinStr:	"HUT"
+	MaxStr:	"HUT"
+	Precision:	-3
+)
+
+(LClass.138
+	IsText:	1
+	Label:	"LIGHTHOUSE"
+	MinStr:	"LIGHTHOUSE"
+	MaxStr:	"LIGHTHOUSE"
+	Precision:	-3
+)
+
+(LClass.139
+	IsText:	1
+	Label:	"OTHER/UNKNOWN"
+	MinStr:	"OTHER/UNKNOWN"
+	MaxStr:	"OTHER/UNKNOWN"
+	Precision:	-3
+)
+
+(LClass.140
+	IsText:	1
+	Label:	"RUINS"
+	MinStr:	"RUINS"
+	MaxStr:	"RUINS"
+	Precision:	-3
+)
+
+(LClass.141
+	IsNoData:	1
+	IsText:	1
+	Label:	"Keine Daten"
+	Precision:	-3
+)
+
+(BMkSym.142
+	Color:	143
+	BgColor:	144
+	Font:	145
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.143
+	Name:	"Transparent"
+)
+
+(TClr.144
+	Name:	"Transparent"
+)
+
+(NFont.145
+	Family:	146
+	Name:	147
+	Style:	148
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.146
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.147
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.148
+	S:	"Normal"
+)
+
+(NameDict.149
+)
+
+(NameDict.150
+)
+
+(Thresh.151
+)
+
+(GSet.152
+)
+
+(TxPosPt.153
+	HAlign:	4
+	VAlign:	3
+)
+
+(FTheme.154
+	Name:	"Political Map"
+	Source:	155
+	Flags:	0x07
+	Legend:	171
+	Threshold:	184
+	View:	6
+	GSet:	185
+	LegEditScript:	"View.EditLegend"
+	TxPos:	186
+	LabelField:	165
+	AttrRules:	187
+	AttrRules:	188
+	AttrRules:	189
+	AttrRules:	190
+	AttrRules:	191
+	AttrRules:	192
+	AttrRules:	193
+	AttrRules:	194
+	SnapTolCursor:	1
+)
+
+(ShpSrc.155
+	Name:	156
+	FTab:	158
+)
+
+(SrcName.156
+	FileName:	157
+	Name:	"political.shp"
+	SubName:	"Polygon"
+	OwnerClass:	"ShpSrc"
+)
+
+(FN.157
+	Path:	"Data/iceland/political.shp"
+)
+
+(FTab.158
+	Name:	"political.dbf"
+	BTab:	159
+	Fields:	169
+	Fields:	160
+	Fields:	161
+	Fields:	162
+	Fields:	163
+	Fields:	164
+	Fields:	165
+	Fields:	166
+	Fields:	167
+	SelBits:	170
+	FSrc:	155
+)
+
+(dBASE.159
+	Name:	"political.dbf"
+	Fields:	160
+	Fields:	161
+	Fields:	162
+	Fields:	163
+	Fields:	164
+	Fields:	165
+	Fields:	166
+	Fields:	167
+	FileName:	168
+)
+
+(Field.160
+	Name:	"Area"
+	Btab:	159
+	Alias:	"Area"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.161
+	Name:	"Perimeter"
+	Btab:	159
+	Alias:	"Perimeter"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.162
+	Name:	"Ponet_"
+	Btab:	159
+	Alias:	"Ponet_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.163
+	Name:	"Ponet_id"
+	Btab:	159
+	Alias:	"Ponet_id"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.164
+	Name:	"Popytype"
+	Btab:	159
+	Alias:	"Popytype"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.165
+	Name:	"Popyreg"
+	Btab:	159
+	Alias:	"Popyreg"
+	Visible:	1
+	Type:	4
+	Order:	-1
+)
+
+(Field.166
+	Name:	"Popycoun"
+	Btab:	159
+	Alias:	"Popycoun"
+	Visible:	1
+	Type:	4
+	Order:	-1
+)
+
+(Field.167
+	Name:	"Popyadmin"
+	Btab:	159
+	Alias:	"Popyadmin"
+	Visible:	1
+	Type:	4
+	Order:	-1
+)
+
+(FN.168
+	Path:	"Data/iceland/political.dbf"
+)
+
+(Field.169
+	Name:	"Shape"
+	Alias:	"Shape"
+	Visible:	1
+	Type:	19
+	Order:	-1
+)
+
+(Bitmap.170
+	NumBits:	156
+
+)
+
+(Legend.171
+	SymType:	0x02
+	LegType:	0x01
+	ClassType:	0x03
+	Symbols:	172
+	Class:	177
+	StdDevs:	1.00000000000000
+	NullSym:	178
+	NullValues:	182
+	StatValues:	183
+	Precision:	-3
+)
+
+(SymList.172
+	Child:	173
+)
+
+(BShSym.173
+	Color:	174
+	Outline:	1
+	OutlineColor:	175
+	OutlineWidth:	0.10000000000000
+	BgColor:	176
+)
+
+(TClr.174
+	Red:	0x12e
+	Green:	0x6400
+	Blue:	0x63
+)
+
+(TClr.175
+)
+
+(TClr.176
+	Red:	0xffff
+	Green:	0xffff
+	Blue:	0xffff
+)
+
+(LClass.177
+	IsText:	1
+	Precision:	-3
+)
+
+(BShSym.178
+	Color:	179
+	Outline:	1
+	OutlineColor:	180
+	OutlineWidth:	0.10000000000000
+	BgColor:	181
+)
+
+(TClr.179
+	Name:	"Transparent"
+)
+
+(TClr.180
+	Name:	"Transparent"
+)
+
+(TClr.181
+	Red:	0xffff
+	Green:	0xffff
+	Blue:	0xffff
+)
+
+(NameDict.182
+)
+
+(NameDict.183
+)
+
+(Thresh.184
+)
+
+(GSet.185
+)
+
+(TxPosPly.186
+	HAlign:	3
+	VAlign:	3
+)
+
+(AttrSingle.187
+	FTab:	158
+	Field:	160
+	UnionRule:	5
+	SplitRule:	3
+)
+
+(AttrSingle.188
+	FTab:	158
+	Field:	161
+	UnionRule:	6
+	SplitRule:	4
+)
+
+(AttrSingle.189
+	FTab:	158
+	Field:	162
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.190
+	FTab:	158
+	Field:	163
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.191
+	FTab:	158
+	Field:	164
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.192
+	FTab:	158
+	Field:	165
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.193
+	FTab:	158
+	Field:	166
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.194
+	FTab:	158
+	Field:	167
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(View.195
+	Name:	"View of Iceland with Cultural Landmarks and Roads"
+	Creator:	"Test A. Little"
+	CreationDate:	"Montag, 15. September 2003 10:27:38"
+	GUIName:	"View"
+	Win:	196
+	CSMgr:	197
+	DocExts:	199
+	DocExts:	200
+	Graphics:	201
+	Theme:	208
+	Theme:	257
+	Theme:	343
+	LastScale:	4636161.54196571090000
+	Dpy:	202
+	TOCWidth:	150
+	CoordPrecision:	2
+)
+
+(DocWin.196
+	Owner:	195
+	X:	-4
+	Y:	-4
+	W:	1034
+	H:	643
+)
+
+(CSMgr.197
+	Client:	198
+)
+
+(CSClient.198
+	Client:	199
+	ReqName:	"ClientNfy"
+)
+
+(PanMgr.199
+	Doc:	195
+)
+
+(DocAct.200
+	Doc:	195
+)
+
+(GList.201
+	Dpy:	202
+	FormatNumb:	207
+)
+
+(MapDpy.202
+	Left:	-22.73219300137291
+	Bottom:	63.85512158261069
+	Top:	66.57720867977865
+	Right:	-13.14576248989830
+	ReportUnits:	4
+	Units:	10
+	Scale:	203
+	FrameTop:	6.37500000000000
+	FrameRight:	9.05208333333333
+	PageDpy:	204
+	FitToPage:	1
+	MouseLoc:	206
+)
+
+(Numb.203
+	N:	0.94426004783515
+)
+
+(PageDpy.204
+	Top:	6.37500000000000
+	Right:	9.05208333333333
+	ReportUnits:	1
+	Units:	1
+	Scale:	205
+	ZoomRight:	9.05208333333333
+	ZoomTop:	6.37500000000000
+	GridSpacingX:	0.25000000000000
+	GridSpacingY:	0.25000000000000
+)
+
+(Numb.205
+	N:	0.11047180667434
+)
+
+(PointD.206
+	x:	-13.36639380201509
+	y:	68.49254011612904
+)
+
+(Numb.207
+)
+
+(FTheme.208
+	Name:	"Roads"
+	Source:	209
+	Flags:	0x06
+	Legend:	226
+	Threshold:	245
+	View:	195
+	GSet:	246
+	LegEditScript:	"View.EditLegend"
+	TxPos:	247
+	AttrRules:	248
+	AttrRules:	249
+	AttrRules:	250
+	AttrRules:	251
+	AttrRules:	252
+	AttrRules:	253
+	AttrRules:	254
+	AttrRules:	255
+	AttrRules:	256
+	SnapTolCursor:	1
+)
+
+(ShpSrc.209
+	Name:	210
+	FTab:	212
+)
+
+(SrcName.210
+	FileName:	211
+	Name:	"roads-line.shp"
+	SubName:	"Arc"
+	OwnerClass:	"ShpSrc"
+)
+
+(FN.211
+	Path:	"Data/iceland/roads-line.shp"
+)
+
+(FTab.212
+	Name:	"roads-line.dbf"
+	BTab:	213
+	Fields:	224
+	Fields:	214
+	Fields:	215
+	Fields:	216
+	Fields:	217
+	Fields:	218
+	Fields:	219
+	Fields:	220
+	Fields:	221
+	Fields:	222
+	SelBits:	225
+	FSrc:	209
+)
+
+(dBASE.213
+	Name:	"roads-line.dbf"
+	Fields:	214
+	Fields:	215
+	Fields:	216
+	Fields:	217
+	Fields:	218
+	Fields:	219
+	Fields:	220
+	Fields:	221
+	Fields:	222
+	FileName:	223
+)
+
+(Field.214
+	Name:	"Fnode_"
+	Btab:	213
+	Alias:	"Fnode_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.215
+	Name:	"Tnode_"
+	Btab:	213
+	Alias:	"Tnode_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.216
+	Name:	"Lpoly_"
+	Btab:	213
+	Alias:	"Lpoly_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.217
+	Name:	"Rpoly_"
+	Btab:	213
+	Alias:	"Rpoly_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.218
+	Name:	"Length"
+	Btab:	213
+	Alias:	"Length"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.219
+	Name:	"Rdline_"
+	Btab:	213
+	Alias:	"Rdline_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.220
+	Name:	"Rdline_id"
+	Btab:	213
+	Alias:	"Rdline_id"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.221
+	Name:	"Rdlntype"
+	Btab:	213
+	Alias:	"Rdlntype"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.222
+	Name:	"Rdlnstat"
+	Btab:	213
+	Alias:	"Rdlnstat"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(FN.223
+	Path:	"Data/iceland/roads-line.dbf"
+)
+
+(Field.224
+	Name:	"Shape"
+	Alias:	"Shape"
+	Visible:	1
+	Type:	18
+	Order:	-1
+)
+
+(Bitmap.225
+	NumBits:	839
+
+)
+
+(Legend.226
+	SymType:	0x01
+	LegType:	0x02
+	ClassType:	0x03
+	FieldNames:	227
+	Symbols:	228
+	Class:	237
+	Class:	238
+	Class:	239
+	Class:	240
+	StdDevs:	1.00000000000000
+	NullSym:	241
+	NullValues:	243
+	StatValues:	244
+	Precision:	-3
+)
+
+(AVStr.227
+	S:	"Rdlntype"
+)
+
+(SymList.228
+	Child:	229
+	Child:	231
+	Child:	233
+	Child:	235
+)
+
+(BLnSym.229
+	Color:	230
+	Width:	0.10000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+)
+
+(TClr.230
+)
+
+(BLnSym.231
+	Color:	232
+	Width:	0.10000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+)
+
+(TClr.232
+	Red:	0xa5a5
+	Green:	0xa5a5
+	Blue:	0xa5a5
+)
+
+(BLnSym.233
+	Color:	234
+	Width:	0.10000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+)
+
+(TClr.234
+	Red:	0xffff
+	Green:	0xffff
+	Blue:	0xffff
+)
+
+(BLnSym.235
+	Color:	236
+	Width:	0.10000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+)
+
+(TClr.236
+	Name:	"Transparent"
+)
+
+(LClass.237
+	Label:	"1"
+	MinNum:	2.00000000000000
+	MaxNum:	2.00000000000000
+	Precision:	-3
+)
+
+(LClass.238
+	Label:	"2"
+	MinNum:	3.00000000000000
+	MaxNum:	3.00000000000000
+	Precision:	-3
+)
+
+(LClass.239
+	Label:	"3"
+	MinNum:	4.00000000000000
+	MaxNum:	8.00000000000000
+	Precision:	-3
+)
+
+(LClass.240
+	IsNoData:	1
+	Label:	"Keine Daten"
+	MaxNum:	-1.00000000000000
+	Precision:	-3
+)
+
+(BLnSym.241
+	Color:	242
+	Width:	0.10000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+	Pattern:	0.00000000000000
+)
+
+(TClr.242
+	Name:	"Transparent"
+)
+
+(NameDict.243
+)
+
+(NameDict.244
+)
+
+(Thresh.245
+)
+
+(GSet.246
+)
+
+(TxPosArc.247
+	HAlign:	3
+	VAlign:	1
+)
+
+(AttrSingle.248
+	FTab:	212
+	Field:	214
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.249
+	FTab:	212
+	Field:	215
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.250
+	FTab:	212
+	Field:	216
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.251
+	FTab:	212
+	Field:	217
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.252
+	FTab:	212
+	Field:	218
+	UnionRule:	6
+	SplitRule:	4
+)
+
+(AttrSingle.253
+	FTab:	212
+	Field:	219
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.254
+	FTab:	212
+	Field:	220
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.255
+	FTab:	212
+	Field:	221
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(AttrSingle.256
+	FTab:	212
+	Field:	222
+	UnionRule:	1
+	SplitRule:	1
+)
+
+(FTheme.257
+	Name:	"Cultural Landmarks"
+	Source:	258
+	Flags:	0x06
+	Legend:	272
+	Threshold:	340
+	View:	195
+	GSet:	341
+	LegEditScript:	"View.EditLegend"
+	TxPos:	342
+	LabelField:	267
+	SnapTolCursor:	1
+)
+
+(ShpSrc.258
+	Name:	259
+	FTab:	261
+)
+
+(SrcName.259
+	FileName:	260
+	Name:	"cultural_landmark-point.shp"
+	SubName:	"Point"
+	OwnerClass:	"ShpSrc"
+)
+
+(FN.260
+	Path:	"Data/iceland/cultural_landmark-point.shp"
+)
+
+(FTab.261
+	Name:	"cultural_landmark-point.dbf"
+	BTab:	262
+	Fields:	270
+	Fields:	263
+	Fields:	264
+	Fields:	265
+	Fields:	266
+	Fields:	267
+	Fields:	268
+	SelBits:	271
+	FSrc:	258
+)
+
+(dBASE.262
+	Name:	"cultural_landmark-point.dbf"
+	Fields:	263
+	Fields:	264
+	Fields:	265
+	Fields:	266
+	Fields:	267
+	Fields:	268
+	FileName:	269
+)
+
+(Field.263
+	Name:	"Area"
+	Btab:	262
+	Alias:	"Area"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.264
+	Name:	"Perimeter"
+	Btab:	262
+	Alias:	"Perimeter"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.265
+	Name:	"Clpoint_"
+	Btab:	262
+	Alias:	"Clpoint_"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.266
+	Name:	"Clpoint_id"
+	Btab:	262
+	Alias:	"Clpoint_id"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(Field.267
+	Name:	"Clptlabel"
+	Btab:	262
+	Alias:	"Clptlabel"
+	Visible:	1
+	Type:	4
+	Order:	-1
+)
+
+(Field.268
+	Name:	"Clptflag"
+	Btab:	262
+	Alias:	"Clptflag"
+	Visible:	1
+	Type:	9
+	Order:	-1
+)
+
+(FN.269
+	Path:	"Data/iceland/cultural_landmark-point.dbf"
+)
+
+(Field.270
+	Name:	"Shape"
+	Alias:	"Shape"
+	Visible:	1
+	Type:	17
+	Order:	-1
+)
+
+(Bitmap.271
+	NumBits:	34
+
+)
+
+(Legend.272
+	LegType:	0x08
+	ClassType:	0x03
+	FieldNames:	273
+	Symbols:	274
+	Class:	324
+	Class:	325
+	Class:	326
+	Class:	327
+	Class:	328
+	Class:	329
+	Class:	330
+	StdDevs:	1.00000000000000
+	NullSym:	331
+	NullValues:	338
+	StatValues:	339
+	Precision:	-3
+)
+
+(AVStr.273
+	S:	"Clptlabel"
+)
+
+(SymList.274
+	Child:	275
+	Child:	282
+	Child:	289
+	Child:	296
+	Child:	303
+	Child:	310
+	Child:	317
+)
+
+(BMkSym.275
+	Color:	276
+	BgColor:	277
+	Font:	278
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.276
+	Red:	0xffff
+)
+
+(TClr.277
+	Name:	"Transparent"
+)
+
+(NFont.278
+	Family:	279
+	Name:	280
+	Style:	281
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.279
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.280
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.281
+	S:	"Normal"
+)
+
+(BMkSym.282
+	Color:	283
+	BgColor:	284
+	Font:	285
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.283
+	Red:	0xa100
+	Green:	0x6686
+	Blue:	0x32f0
+)
+
+(TClr.284
+	Name:	"Transparent"
+)
+
+(NFont.285
+	Family:	286
+	Name:	287
+	Style:	288
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.286
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.287
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.288
+	S:	"Normal"
+)
+
+(BMkSym.289
+	Color:	290
+	BgColor:	291
+	Font:	292
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.290
+	Red:	0x170b
+	Green:	0xdb
+	Blue:	0xdc00
+)
+
+(TClr.291
+	Name:	"Transparent"
+)
+
+(NFont.292
+	Family:	293
+	Name:	294
+	Style:	295
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.293
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.294
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.295
+	S:	"Normal"
+)
+
+(BMkSym.296
+	Color:	297
+	BgColor:	298
+	Font:	299
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.297
+	Red:	0xffff
+	Green:	0xffff
+)
+
+(TClr.298
+	Name:	"Transparent"
+)
+
+(NFont.299
+	Family:	300
+	Name:	301
+	Style:	302
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.300
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.301
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.302
+	S:	"Normal"
+)
+
+(BMkSym.303
+	Color:	304
+	BgColor:	305
+	Font:	306
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.304
+	Red:	0xffff
+	Green:	0xffff
+	Blue:	0xffff
+)
+
+(TClr.305
+	Name:	"Transparent"
+)
+
+(NFont.306
+	Family:	307
+	Name:	308
+	Style:	309
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.307
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.308
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.309
+	S:	"Normal"
+)
+
+(BMkSym.310
+	Color:	311
+	BgColor:	312
+	Font:	313
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.311
+)
+
+(TClr.312
+	Name:	"Transparent"
+)
+
+(NFont.313
+	Family:	314
+	Name:	315
+	Style:	316
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.314
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.315
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.316
+	S:	"Normal"
+)
+
+(BMkSym.317
+	Color:	318
+	BgColor:	319
+	Font:	320
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.318
+	Name:	"Transparent"
+)
+
+(TClr.319
+	Name:	"Transparent"
+)
+
+(NFont.320
+	Family:	321
+	Name:	322
+	Style:	323
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.321
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.322
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.323
+	S:	"Normal"
+)
+
+(LClass.324
+	IsText:	1
+	Label:	"BUILDING"
+	MinStr:	"BUILDING"
+	MaxStr:	"BUILDING"
+	Precision:	-3
+)
+
+(LClass.325
+	IsText:	1
+	Label:	"FARM"
+	MinStr:	"FARM"
+	MaxStr:	"FARM"
+	Precision:	-3
+)
+
+(LClass.326
+	IsText:	1
+	Label:	"HUT"
+	MinStr:	"HUT"
+	MaxStr:	"HUT"
+	Precision:	-3
+)
+
+(LClass.327
+	IsText:	1
+	Label:	"LIGHTHOUSE"
+	MinStr:	"LIGHTHOUSE"
+	MaxStr:	"LIGHTHOUSE"
+	Precision:	-3
+)
+
+(LClass.328
+	IsText:	1
+	Label:	"OTHER/UNKNOWN"
+	MinStr:	"OTHER/UNKNOWN"
+	MaxStr:	"OTHER/UNKNOWN"
+	Precision:	-3
+)
+
+(LClass.329
+	IsText:	1
+	Label:	"RUINS"
+	MinStr:	"RUINS"
+	MaxStr:	"RUINS"
+	Precision:	-3
+)
+
+(LClass.330
+	IsNoData:	1
+	IsText:	1
+	Label:	"Keine Daten"
+	Precision:	-3
+)
+
+(BMkSym.331
+	Color:	332
+	BgColor:	333
+	Font:	334
+	Size:	8.00000000000000
+	Pattern:	35
+	Angle:	360.00000000000000
+)
+
+(TClr.332
+	Name:	"Transparent"
+)
+
+(TClr.333
+	Name:	"Transparent"
+)
+
+(NFont.334
+	Family:	335
+	Name:	336
+	Style:	337
+	Weight:	1
+	Wideness:	1
+)
+
+(AVStr.335
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.336
+	S:	"ESRI Geometric Symbols"
+)
+
+(AVStr.337
+	S:	"Normal"
+)
+
+(NameDict.338
+)
+
+(NameDict.339
+)
+
+(Thresh.340
+)
+
+(GSet.341
+)
+
+(TxPosPt.342
+	HAlign:	4
+	VAlign:	3
+)
+
+(ITheme.343
+	Name:	"Iceland"
+	Source:	344
+	Flags:	0x07
+	Legend:	349
+	Threshold:	609
+	View:	195
+	GSet:	610
+	LegEditScript:	"View.EditLegend"
+)
+
+(ISrc.344
+	Name:	345
+	MapBox:	347
+	BandStats:	348
+)
+
+(SrcName.345
+	FileName:	346
+	Name:	"island.tif"
+	OwnerClass:	"ISrc"
+)
+
+(FN.346
+	Path:	"Data/iceland/island.tif"
+)
+
+(RectD.347
+	Left:	-24.55000000000000
+	Top:	66.56666700000000
+	Right:	-13.49166700000083
+	Bottom:	63.28333299999988
+)
+
+(BStat.348
+	Max:	255.00000000000000
+	Mean:	127.50000000000000
+	StDv:	63.75000000000000
+)
+
+(SBILeg.349
+	PixelLUT:	350
+	ClrMap:	351
+)
+
+(ILUTIdn.350
+)
+
+(TClrMap.351
+	Colors:	352
+	Colors:	353
+	Colors:	354
+	Colors:	355
+	Colors:	356
+	Colors:	357
+	Colors:	358
+	Colors:	359
+	Colors:	360
+	Colors:	361
+	Colors:	362
+	Colors:	363
+	Colors:	364
+	Colors:	365
+	Colors:	366
+	Colors:	367
+	Colors:	368
+	Colors:	369
+	Colors:	370
+	Colors:	371
+	Colors:	372
+	Colors:	373
+	Colors:	374
+	Colors:	375
+	Colors:	376
+	Colors:	377
+	Colors:	378
+	Colors:	379
+	Colors:	380
+	Colors:	381
+	Colors:	382
+	Colors:	383
+	Colors:	384
+	Colors:	385
+	Colors:	386
+	Colors:	387
+	Colors:	388
+	Colors:	389
+	Colors:	390
+	Colors:	391
+	Colors:	392
+	Colors:	393
+	Colors:	394
+	Colors:	395
+	Colors:	396
+	Colors:	397
+	Colors:	398
+	Colors:	399
+	Colors:	400
+	Colors:	401
+	Colors:	402
+	Colors:	403
+	Colors:	404
+	Colors:	405
+	Colors:	406
+	Colors:	407
+	Colors:	408
+	Colors:	409
+	Colors:	410
+	Colors:	411
+	Colors:	412
+	Colors:	413
+	Colors:	414
+	Colors:	415
+	Colors:	416
+	Colors:	417
+	Colors:	418
+	Colors:	419
+	Colors:	420
+	Colors:	421
+	Colors:	422
+	Colors:	423
+	Colors:	424
+	Colors:	425
+	Colors:	426
+	Colors:	427
+	Colors:	428
+	Colors:	429
+	Colors:	430
+	Colors:	431
+	Colors:	432
+	Colors:	433
+	Colors:	434
+	Colors:	435
+	Colors:	436
+	Colors:	437
+	Colors:	438
+	Colors:	439
+	Colors:	440
+	Colors:	441
+	Colors:	442
+	Colors:	443
+	Colors:	444
+	Colors:	445
+	Colors:	446
+	Colors:	447
+	Colors:	448
+	Colors:	449
+	Colors:	450
+	Colors:	451
+	Colors:	452
+	Colors:	453
+	Colors:	454
+	Colors:	455
+	Colors:	456
+	Colors:	457
+	Colors:	458
+	Colors:	459
+	Colors:	460
+	Colors:	461
+	Colors:	462
+	Colors:	463
+	Colors:	464
+	Colors:	465
+	Colors:	466
+	Colors:	467
+	Colors:	468
+	Colors:	469
+	Colors:	470
+	Colors:	471
+	Colors:	472
+	Colors:	473
+	Colors:	474
+	Colors:	475
+	Colors:	476
+	Colors:	477
+	Colors:	478
+	Colors:	479
+	Colors:	480
+	Colors:	481
+	Colors:	482
+	Colors:	483
+	Colors:	484
+	Colors:	485
+	Colors:	486
+	Colors:	487
+	Colors:	488
+	Colors:	489
+	Colors:	490
+	Colors:	491
+	Colors:	492
+	Colors:	493
+	Colors:	494
+	Colors:	495
+	Colors:	496
+	Colors:	497
+	Colors:	498
+	Colors:	499
+	Colors:	500
+	Colors:	501
+	Colors:	502
+	Colors:	503
+	Colors:	504
+	Colors:	505
+	Colors:	506
+	Colors:	507
+	Colors:	508
+	Colors:	509
+	Colors:	510
+	Colors:	511
+	Colors:	512
+	Colors:	513
+	Colors:	514
+	Colors:	515
+	Colors:	516
+	Colors:	517
+	Colors:	518
+	Colors:	519
+	Colors:	520
+	Colors:	521
+	Colors:	522
+	Colors:	523
+	Colors:	524
+	Colors:	525
+	Colors:	526
+	Colors:	527
+	Colors:	528
+	Colors:	529
+	Colors:	530
+	Colors:	531
+	Colors:	532
+	Colors:	533
+	Colors:	534
+	Colors:	535
+	Colors:	536
+	Colors:	537
+	Colors:	538
+	Colors:	539
+	Colors:	540
+	Colors:	541
+	Colors:	542
+	Colors:	543
+	Colors:	544
+	Colors:	545
+	Colors:	546
+	Colors:	547
+	Colors:	548
+	Colors:	549
+	Colors:	550
+	Colors:	551
+	Colors:	552
+	Colors:	553
+	Colors:	554
+	Colors:	555
+	Colors:	556
+	Colors:	557
+	Colors:	558
+	Colors:	559
+	Colors:	560
+	Colors:	561
+	Colors:	562
+	Colors:	563
+	Colors:	564
+	Colors:	565
+	Colors:	566
+	Colors:	567
+	Colors:	568
+	Colors:	569
+	Colors:	570
+	Colors:	571
+	Colors:	572
+	Colors:	573
+	Colors:	574
+	Colors:	575
+	Colors:	576
+	Colors:	577
+	Colors:	578
+	Colors:	579
+	Colors:	580
+	Colors:	581
+	Colors:	582
+	Colors:	583
+	Colors:	584
+	Colors:	585
+	Colors:	586
+	Colors:	587
+	Colors:	588
+	Colors:	589
+	Colors:	590
+	Colors:	591
+	Colors:	592
+	Colors:	593
+	Colors:	594
+	Colors:	595
+	Colors:	596
+	Colors:	597
+	Colors:	598
+	Colors:	599
+	Colors:	600
+	Colors:	601
+	Colors:	602
+	Colors:	603
+	Colors:	604
+	Colors:	605
+	Colors:	606
+	Colors:	607
+	NoDataClr:	608
+)
+
+(TClr.352
+	Red:	0xe00
+	Green:	0x9600
+	Blue:	0x200
+)
+
+(TClr.353
+	Red:	0x200
+	Green:	0xc600
+	Blue:	0x200
+)
+
+(TClr.354
+	Red:	0x3a00
+	Green:	0x7e00
+	Blue:	0x600
+)
+
+(TClr.355
+	Red:	0x7200
+	Green:	0x6600
+	Blue:	0x1e00
+)
+
+(TClr.356
+	Red:	0x7a00
+	Green:	0x7600
+	Blue:	0x2600
+)
+
+(TClr.357
+	Red:	0x8e00
+	Green:	0x8e00
+	Blue:	0x2e00
+)
+
+(TClr.358
+	Red:	0x200
+	Green:	0xb200
+	Blue:	0x200
+)
+
+(TClr.359
+	Red:	0x1a00
+	Green:	0xba00
+	Blue:	0x4e00
+)
+
+(TClr.360
+	Red:	0x200
+	Green:	0x9e00
+	Blue:	0x200
+)
+
+(TClr.361
+	Red:	0x5200
+	Green:	0x6600
+	Blue:	0xe600
+)
+
+(TClr.362
+	Red:	0x3600
+	Green:	0x8e00
+	Blue:	0x9a00
+)
+
+(TClr.363
+	Red:	0x200
+	Green:	0xce00
+	Blue:	0x200
+)
+
+(TClr.364
+	Red:	0x3200
+	Green:	0x8200
+	Blue:	0x200
+)
+
+(TClr.365
+	Red:	0x6600
+	Green:	0x6a00
+	Blue:	0x1600
+)
+
+(TClr.366
+	Red:	0xe600
+	Green:	0xe200
+	Blue:	0xe00
+)
+
+(TClr.367
+	Red:	0x200
+	Green:	0xd200
+	Blue:	0x200
+)
+
+(TClr.368
+	Red:	0x200
+	Green:	0xaa00
+	Blue:	0x200
+)
+
+(TClr.369
+	Red:	0x5a00
+	Green:	0x7200
+	Blue:	0x1200
+)
+
+(TClr.370
+	Red:	0x200
+	Green:	0xd600
+	Blue:	0x200
+)
+
+(TClr.371
+	Red:	0xa600
+	Green:	0x9e00
+	Blue:	0x3200
+)
+
+(TClr.372
+	Red:	0xde00
+	Green:	0xda00
+	Blue:	0x1200
+)
+
+(TClr.373
+	Red:	0x2200
+	Green:	0x8a00
+	Blue:	0x200
+)
+
+(TClr.374
+	Red:	0x200
+	Green:	0xda00
+	Blue:	0x200
+)
+
+(TClr.375
+	Red:	0x200
+	Green:	0xb600
+	Blue:	0x200
+)
+
+(TClr.376
+	Red:	0xce00
+	Green:	0xc600
+	Blue:	0x1e00
+)
+
+(TClr.377
+	Red:	0x4e00
+	Green:	0x7600
+	Blue:	0xa00
+)
+
+(TClr.378
+	Red:	0x200
+	Green:	0xa200
+	Blue:	0x200
+)
+
+(TClr.379
+	Red:	0xda00
+	Green:	0xd600
+	Blue:	0x1600
+)
+
+(TClr.380
+	Red:	0x8a00
+	Green:	0x8e00
+	Blue:	0x2a00
+)
+
+(TClr.381
+	Red:	0x7a00
+	Green:	0x7600
+	Blue:	0x2200
+)
+
+(TClr.382
+	Red:	0x200
+	Green:	0xe200
+	Blue:	0x200
+)
+
+(TClr.383
+	Red:	0xa200
+	Green:	0x9a00
+	Blue:	0x3200
+)
+
+(TClr.384
+	Red:	0x3a00
+	Green:	0x7e00
+	Blue:	0x200
+)
+
+(TClr.385
+	Red:	0x200
+	Green:	0xbe00
+	Blue:	0x200
+)
+
+(TClr.386
+	Red:	0x1600
+	Green:	0x9200
+	Blue:	0x200
+)
+
+(TClr.387
+	Red:	0x7a00
+	Green:	0x7e00
+	Blue:	0x2600
+)
+
+(TClr.388
+	Red:	0x1e00
+	Green:	0x8e00
+	Blue:	0x200
+)
+
+(TClr.389
+	Red:	0xd600
+	Green:	0xd200
+	Blue:	0x1a00
+)
+
+(TClr.390
+	Red:	0x7a00
+	Green:	0x6e00
+	Blue:	0x2200
+)
+
+(TClr.391
+	Red:	0xca00
+	Green:	0xc600
+	Blue:	0x1e00
+)
+
+(TClr.392
+	Red:	0x4a00
+	Green:	0x7a00
+	Blue:	0xa00
+)
+
+(TClr.393
+	Red:	0xe00
+	Green:	0x9a00
+	Blue:	0x200
+)
+
+(TClr.394
+	Red:	0xd200
+	Green:	0xce00
+	Blue:	0x1a00
+)
+
+(TClr.395
+	Red:	0xc600
+	Green:	0xc200
+	Blue:	0x2200
+)
+
+(TClr.396
+	Red:	0x8200
+	Green:	0x8a00
+	Blue:	0x2a00
+)
+
+(TClr.397
+	Red:	0x2a00
+	Green:	0x8600
+	Blue:	0x200
+)
+
+(TClr.398
+	Red:	0x4600
+	Green:	0x7a00
+	Blue:	0x600
+)
+
+(TClr.399
+	Red:	0xa00
+	Green:	0x9a00
+	Blue:	0x200
+)
+
+(TClr.400
+	Red:	0xba00
+	Green:	0xb200
+	Blue:	0x2a00
+)
+
+(TClr.401
+	Red:	0x200
+	Green:	0xe600
+	Blue:	0x200
+)
+
+(TClr.402
+	Red:	0x200
+	Green:	0xde00
+	Blue:	0x200
+)
+
+(TClr.403
+	Red:	0x1a00
+	Green:	0x9200
+	Blue:	0x200
+)
+
+(TClr.404
+	Red:	0x6a00
+	Green:	0x6a00
+	Blue:	0x1600
+)
+
+(TClr.405
+	Red:	0x600
+	Green:	0x9e00
+	Blue:	0x200
+)
+
+(TClr.406
+	Red:	0x2200
+	Green:	0x8e00
+	Blue:	0x200
+)
+
+(TClr.407
+	Red:	0x200
+	Green:	0xa600
+	Blue:	0x200
+)
+
+(TClr.408
+	Red:	0xc600
+	Green:	0xbe00
+	Blue:	0x2200
+)
+
+(TClr.409
+	Red:	0x7a00
+	Green:	0x8200
+	Blue:	0x2600
+)
+
+(TClr.410
+	Red:	0x200
+	Green:	0xc200
+	Blue:	0x200
+)
+
+(TClr.411
+	Red:	0x200
+	Green:	0xca00
+	Blue:	0x200
+)
+
+(TClr.412
+	Red:	0x200
+	Green:	0xae00
+	Blue:	0x200
+)
+
+(TClr.413
+	Red:	0x1200
+	Green:	0x9600
+	Blue:	0x200
+)
+
+(TClr.414
+	Red:	0x5600
+	Green:	0x7200
+	Blue:	0xe00
+)
+
+(TClr.415
+	Red:	0x9e00
+	Green:	0x9a00
+	Blue:	0x2e00
+)
+
+(TClr.416
+	Red:	0x200
+	Green:	0xba00
+	Blue:	0x200
+)
+
+(TClr.417
+	Red:	0x3600
+	Green:	0x8200
+	Blue:	0x200
+)
+
+(TClr.418
+	Red:	0x5e00
+	Green:	0x6e00
+	Blue:	0x1200
+)
+
+(TClr.419
+	Red:	0x2a00
+	Green:	0x8a00
+	Blue:	0x200
+)
+
+(TClr.420
+	Red:	0x4200
+	Green:	0x7a00
+	Blue:	0x600
+)
+
+(TClr.421
+	Red:	0x7a00
+	Green:	0x6a00
+	Blue:	0x1e00
+)
+
+(TClr.422
+	Red:	0x7200
+	Green:	0x6600
+	Blue:	0x1a00
+)
+
+(TClr.423
+	Red:	0x2e00
+	Green:	0x8600
+	Blue:	0x200
+)
+
+(TClr.424
+	Red:	0x9a00
+	Green:	0x9600
+	Blue:	0x2e00
+)
+
+(TClr.425
+	Red:	0x7a00
+	Green:	0x7200
+	Blue:	0x2200
+)
+
+(TClr.426
+	Red:	0x1600
+	Green:	0x9600
+	Blue:	0x200
+)
+
+(TClr.427
+	Red:	0x5e00
+	Green:	0x7200
+	Blue:	0x1200
+)
+
+(TClr.428
+	Red:	0x4200
+	Green:	0x7e00
+	Blue:	0x600
+)
+
+(TClr.429
+	Red:	0x8200
+	Green:	0x8600
+	Blue:	0x2a00
+)
+
+(TClr.430
+	Red:	0x5200
+	Green:	0x7600
+	Blue:	0xe00
+)
+
+(TClr.431
+	Red:	0x7600
+	Green:	0x6600
+	Blue:	0x1e00
+)
+
+(TClr.432
+	Red:	0x2600
+	Green:	0x8a00
+	Blue:	0x200
+)
+
+(TClr.433
+	Red:	0x7a00
+	Green:	0x7a00
+	Blue:	0x2600
+)
+
+(TClr.434
+	Red:	0x7a00
+	Green:	0x8600
+	Blue:	0x2a00
+)
+
+(TClr.435
+	Red:	0xb600
+	Green:	0xae00
+	Blue:	0x2a00
+)
+
+(TClr.436
+	Red:	0x6e00
+	Green:	0x6a00
+	Blue:	0x1a00
+)
+
+(TClr.437
+	Red:	0x7a00
+	Green:	0x6600
+	Blue:	0x1e00
+)
+
+(TClr.438
+	Red:	0x1e00
+	Green:	0x9200
+	Blue:	0x200
+)
+
+(TClr.439
+	Red:	0xb200
+	Green:	0xaa00
+	Blue:	0x2e00
+)
+
+(TClr.440
+	Red:	0x5600
+	Green:	0x7600
+	Blue:	0xe00
+)
+
+(TClr.441
+	Red:	0x9600
+	Green:	0x9600
+	Blue:	0x2e00
+)
+
+(TClr.442
+	Red:	0x3a00
+	Green:	0x8200
+	Blue:	0x200
+)
+
+(TClr.443
+	Red:	0x3e00
+	Green:	0x7e00
+	Blue:	0x600
+)
+
+(TClr.444
+	Red:	0x6200
+	Green:	0x6e00
+	Blue:	0x1200
+)
+
+(TClr.445
+	Red:	0x9600
+	Green:	0x9200
+	Blue:	0x2e00
+)
+
+(TClr.446
+	Red:	0xe600
+	Green:	0xe600
+	Blue:	0xe00
+)
+
+(TClr.447
+	Red:	0x6600
+	Green:	0x6e00
+	Blue:	0x1600
+)
+
+(TClr.448
+	Red:	0x7200
+	Green:	0x6a00
+	Blue:	0x1a00
+)
+
+(TClr.449
+	Red:	0x8e00
+	Green:	0x9200
+	Blue:	0x2e00
+)
+
+(TClr.450
+	Red:	0x8600
+	Green:	0x8a00
+	Blue:	0x2a00
+)
+
+(TClr.451
+	Red:	0x4e00
+	Green:	0x7600
+	Blue:	0xe00
+)
+
+(TClr.452
+	Red:	0xea00
+	Green:	0xea00
+	Blue:	0xe00
+)
+
+(TClr.453
+	Red:	0x7a00
+	Green:	0x6a00
+	Blue:	0x2200
+)
+
+(TClr.454
+	Red:	0xae00
+	Green:	0xa600
+	Blue:	0x2e00
+)
+
+(TClr.455
+	Red:	0x6a00
+	Green:	0x6a00
+	Blue:	0x1a00
+)
+
+(TClr.456
+	Red:	0x7a00
+	Green:	0x8200
+	Blue:	0x2a00
+)
+
+(TClr.457
+	Red:	0x5600
+	Green:	0x7200
+	Blue:	0x1200
+)
+
+(TClr.458
+	Red:	0x4600
+	Green:	0x7a00
+	Blue:	0xa00
+)
+
+(TClr.459
+	Red:	0x6200
+	Green:	0x6e00
+	Blue:	0x1600
+)
+
+(TClr.460
+	Red:	0xee00
+	Green:	0xee00
+	Blue:	0xa00
+)
+
+(TClr.461
+	Red:	0x7e00
+	Green:	0x8600
+	Blue:	0x2a00
+)
+
+(TClr.462
+	Red:	0x8a00
+	Green:	0x8a00
+	Blue:	0x2a00
+)
+
+(TClr.463
+	Red:	0xae00
+	Green:	0xa600
+	Blue:	0x3200
+)
+
+(TClr.464
+	Red:	0xf200
+	Green:	0xf200
+	Blue:	0x600
+)
+
+(TClr.465
+	Red:	0xc200
+	Green:	0xba00
+	Blue:	0x2600
+)
+
+(TClr.466
+	Red:	0xaa00
+	Green:	0x9e00
+	Blue:	0x3200
+)
+
+(TClr.467
+	Red:	0x9e00
+	Green:	0x9600
+	Blue:	0x2e00
+)
+
+(TClr.468
+	Red:	0xaa00
+	Green:	0xa200
+	Blue:	0x3200
+)
+
+(TClr.469
+	Red:	0xf600
+	Green:	0xf600
+	Blue:	0x600
+)
+
+(TClr.470
+	Red:	0x9200
+	Green:	0x9200
+	Blue:	0x2e00
+)
+
+(TClr.471
+	Red:	0xe200
+	Green:	0xde00
+	Blue:	0x1200
+)
+
+(TClr.472
+	Red:	0xbe00
+	Green:	0xb600
+	Blue:	0x2600
+)
+
+(TClr.473
+	Red:	0xce00
+	Green:	0xca00
+	Blue:	0x1e00
+)
+
+(TClr.474
+	Red:	0xa200
+	Green:	0x9e00
+	Blue:	0x3200
+)
+
+(TClr.475
+	Red:	0xb600
+	Green:	0xae00
+	Blue:	0x2e00
+)
+
+(TClr.476
+	Red:	0xae00
+	Green:	0xa200
+	Blue:	0x3200
+)
+
+(TClr.477
+	Red:	0xfa00
+	Green:	0xfa00
+	Blue:	0x200
+)
+
+(TClr.478
+	Red:	0xd200
+	Green:	0xca00
+	Blue:	0x1a00
+)
+
+(TClr.479
+	Red:	0xe200
+	Green:	0xe200
+	Blue:	0x1200
+)
+
+(TClr.480
+	Red:	0xf600
+	Green:	0xf200
+	Blue:	0x600
+)
+
+(TClr.481
+	Red:	0xea00
+	Green:	0xe600
+	Blue:	0xe00
+)
+
+(TClr.482
+	Red:	0xb600
+	Green:	0xaa00
+	Blue:	0x2e00
+)
+
+(TClr.483
+	Red:	0xb200
+	Green:	0xa600
+	Blue:	0x2e00
+)
+
+(TClr.484
+	Red:	0xfa00
+	Green:	0xf600
+	Blue:	0x600
+)
+
+(TClr.485
+	Red:	0xca00
+	Green:	0xc200
+	Blue:	0x2200
+)
+
+(TClr.486
+	Red:	0xde00
+	Green:	0xda00
+	Blue:	0x1600
+)
+
+(TClr.487
+	Red:	0xbe00
+	Green:	0xb600
+	Blue:	0x2a00
+)
+
+(TClr.488
+	Red:	0xf200
+	Green:	0xee00
+	Blue:	0xa00
+)
+
+(TClr.489
+	Red:	0xe600
+	Green:	0xe200
+	Blue:	0x1200
+)
+
+(TClr.490
+	Red:	0xee00
+	Green:	0xea00
+	Blue:	0xa00
+)
+
+(TClr.491
+	Red:	0xf200
+	Green:	0xf200
+	Blue:	0xa00
+)
+
+(TClr.492
+	Red:	0xfa00
+	Green:	0xfa00
+	Blue:	0x600
+)
+
+(TClr.493
+	Red:	0x4000
+	Green:	0x4000
+)
+
+(TClr.494
+	Red:	0x6400
+	Green:	0x6400
+	Blue:	0x5800
+)
+
+(TClr.495
+	Red:	0x4000
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.496
+	Red:	0x9f00
+	Green:	0x9e00
+	Blue:	0x600
+)
+
+(TClr.497
+	Red:	0x800
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.498
+	Red:	0xfc00
+	Green:	0x8000
+)
+
+(TClr.499
+	Red:	0xbf00
+	Green:	0xfb00
+)
+
+(TClr.500
+	Red:	0xa00
+	Green:	0x3d00
+	Blue:	0x9100
+)
+
+(TClr.501
+	Green:	0x800
+	Blue:	0x4000
+)
+
+(TClr.502
+	Red:	0x4100
+	Green:	0x3d00
+	Blue:	0x2e00
+)
+
+(TClr.503
+	Red:	0x800
+	Green:	0x800
+	Blue:	0x4000
+)
+
+(TClr.504
+	Green:	0x3c00
+	Blue:	0x600
+)
+
+(TClr.505
+	Green:	0x800
+	Blue:	0x4000
+)
+
+(TClr.506
+	Red:	0xfa00
+	Green:	0x3c00
+	Blue:	0x600
+)
+
+(TClr.507
+	Red:	0xbf00
+	Green:	0x800
+	Blue:	0x4000
+)
+
+(TClr.508
+	Red:	0x5700
+	Green:	0x3c00
+	Blue:	0x2500
+)
+
+(TClr.509
+	Red:	0x4000
+	Green:	0x800
+	Blue:	0x800
+)
+
+(TClr.510
+	Red:	0x4000
+	Green:	0x3c00
+)
+
+(TClr.511
+	Red:	0x800
+	Green:	0x800
+)
+
+(TClr.512
+	Red:	0x4000
+	Green:	0x3c00
+	Blue:	0x600
+)
+
+(TClr.513
+	Red:	0x800
+	Green:	0x800
+	Blue:	0x4000
+)
+
+(TClr.514
+	Green:	0x6400
+)
+
+(TClr.515
+	Green:	0x4000
+)
+
+(TClr.516
+	Red:	0x9a00
+	Green:	0x2e00
+)
+
+(TClr.517
+	Red:	0x4000
+	Green:	0x4000
+)
+
+(TClr.518
+	Red:	0x2e00
+)
+
+(TClr.519
+	Red:	0x4000
+)
+
+(TClr.520
+	Red:	0x600
+	Green:	0x4000
+	Blue:	0x600
+)
+
+(TClr.521
+	Red:	0x4000
+	Green:	0x800
+	Blue:	0x4000
+)
+
+(TClr.522
+	Red:	0x4000
+	Blue:	0xf600
+)
+
+(TClr.523
+	Red:	0x800
+	Blue:	0xbf00
+)
+
+(TClr.524
+	Red:	0xd800
+	Green:	0x2e00
+	Blue:	0x9000
+)
+
+(TClr.525
+	Red:	0x4000
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.526
+	Red:	0x3900
+	Green:	0x6400
+	Blue:	0x2e00
+)
+
+(TClr.527
+	Red:	0x4000
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.528
+	Red:	0x9f00
+	Green:	0x9e00
+)
+
+(TClr.529
+	Red:	0x800
+	Green:	0x4000
+)
+
+(TClr.530
+	Red:	0xfa00
+	Green:	0xf800
+)
+
+(TClr.531
+	Red:	0xbf00
+	Green:	0xbf00
+)
+
+(TClr.532
+	Red:	0xc300
+	Green:	0x9a00
+	Blue:	0x9f00
+)
+
+(TClr.533
+	Red:	0x4000
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.534
+	Red:	0x700
+	Green:	0x8400
+	Blue:	0x2e00
+)
+
+(TClr.535
+	Red:	0x4000
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.536
+	Green:	0xfc00
+	Blue:	0x600
+)
+
+(TClr.537
+	Green:	0xbf00
+	Blue:	0x4000
+)
+
+(TClr.538
+	Red:	0xa00
+	Green:	0x6400
+)
+
+(TClr.539
+	Green:	0x4000
+)
+
+(TClr.540
+	Red:	0x4b00
+	Green:	0x2e00
+	Blue:	0x6900
+)
+
+(TClr.541
+	Red:	0x800
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.542
+	Red:	0xb00
+	Blue:	0x2e00
+)
+
+(TClr.543
+	Blue:	0x4000
+)
+
+(TClr.544
+	Red:	0x600
+	Green:	0xf900
+)
+
+(TClr.545
+	Red:	0x4000
+	Green:	0xbf00
+)
+
+(TClr.546
+	Red:	0xfa00
+	Blue:	0xf600
+)
+
+(TClr.547
+	Red:	0xbf00
+	Blue:	0xbf00
+)
+
+(TClr.548
+	Red:	0x9a00
+	Green:	0x2e00
+	Blue:	0x9d00
+)
+
+(TClr.549
+	Red:	0x4000
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.550
+	Red:	0x6400
+	Green:	0x6400
+)
+
+(TClr.551
+	Red:	0x4000
+	Green:	0x4000
+)
+
+(TClr.552
+	Red:	0x9f00
+	Green:	0x9e00
+	Blue:	0x600
+)
+
+(TClr.553
+	Red:	0x800
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.554
+	Red:	0xfc00
+	Blue:	0xf700
+)
+
+(TClr.555
+	Red:	0xbf00
+	Blue:	0xbf00
+)
+
+(TClr.556
+	Red:	0x600
+	Green:	0x3d00
+	Blue:	0xec00
+)
+
+(TClr.557
+	Red:	0x4000
+	Green:	0x800
+	Blue:	0x4000
+)
+
+(TClr.558
+	Green:	0x8400
+	Blue:	0xf800
+)
+
+(TClr.559
+	Green:	0x4000
+	Blue:	0xbf00
+)
+
+(TClr.560
+	Red:	0x4000
+	Green:	0xfc00
+)
+
+(TClr.561
+	Red:	0x800
+	Green:	0xbf00
+)
+
+(TClr.562
+	Red:	0xfa00
+	Green:	0x6400
+	Blue:	0xf700
+)
+
+(TClr.563
+	Red:	0xbf00
+	Green:	0x4000
+	Blue:	0xbf00
+)
+
+(TClr.564
+	Red:	0x5700
+	Green:	0x2e00
+	Blue:	0xec00
+)
+
+(TClr.565
+	Red:	0x4000
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.566
+	Red:	0x4000
+	Blue:	0x2e00
+)
+
+(TClr.567
+	Red:	0x800
+	Blue:	0x4000
+)
+
+(TClr.568
+	Green:	0x4000
+	Blue:	0xf800
+)
+
+(TClr.569
+	Green:	0x800
+	Blue:	0xbf00
+)
+
+(TClr.570
+	Blue:	0x3c00
+)
+
+(TClr.571
+	Blue:	0x800
+)
+
+(TClr.572
+	Red:	0x5600
+	Green:	0x2e00
+	Blue:	0x9f00
+)
+
+(TClr.573
+	Red:	0x4000
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.574
+	Red:	0x3900
+	Green:	0x6400
+)
+
+(TClr.575
+	Red:	0x4000
+	Green:	0x4000
+)
+
+(TClr.576
+	Red:	0x9700
+	Green:	0x9e00
+)
+
+(TClr.577
+	Red:	0x4000
+	Green:	0x4000
+)
+
+(TClr.578
+	Red:	0x4000
+	Blue:	0xf600
+)
+
+(TClr.579
+	Red:	0x800
+	Blue:	0xbf00
+)
+
+(TClr.580
+	Red:	0x600
+	Green:	0xb00
+	Blue:	0x9d00
+)
+
+(TClr.581
+	Red:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.582
+	Red:	0x6d00
+	Green:	0x8400
+)
+
+(TClr.583
+	Red:	0x4000
+	Green:	0x4000
+)
+
+(TClr.584
+	Red:	0x3d00
+	Green:	0xfc00
+	Blue:	0x1d00
+)
+
+(TClr.585
+	Red:	0x4000
+	Green:	0xbf00
+	Blue:	0x800
+)
+
+(TClr.586
+	Red:	0xfa00
+	Green:	0x6400
+	Blue:	0xf600
+)
+
+(TClr.587
+	Red:	0xbf00
+	Green:	0x4000
+	Blue:	0xbf00
+)
+
+(TClr.588
+	Red:	0x6c00
+	Green:	0x2e00
+	Blue:	0x900
+)
+
+(TClr.589
+	Red:	0x4000
+	Green:	0x4000
+	Blue:	0x6500
+)
+
+(TClr.590
+	Red:	0x4000
+	Blue:	0x1d00
+)
+
+(TClr.591
+	Red:	0x800
+	Blue:	0x800
+)
+
+(TClr.592
+	Green:	0x4000
+	Blue:	0x1d00
+)
+
+(TClr.593
+	Green:	0x800
+	Blue:	0x800
+)
+
+(TClr.594
+)
+
+(TClr.595
+)
+
+(TClr.596
+	Red:	0x6c00
+	Green:	0xb300
+)
+
+(TClr.597
+	Red:	0x4000
+	Green:	0x4000
+)
+
+(TClr.598
+	Red:	0x3900
+	Green:	0xf900
+	Blue:	0xff00
+)
+
+(TClr.599
+	Red:	0x4000
+	Green:	0xbf00
+	Blue:	0x7f00
+)
+
+(TClr.600
+	Red:	0x9700
+	Green:	0x6f00
+	Blue:	0x600
+)
+
+(TClr.601
+	Red:	0x4000
+	Green:	0x4000
+	Blue:	0x4000
+)
+
+(TClr.602
+	Red:	0xe400
+	Green:	0xb200
+)
+
+(TClr.603
+	Red:	0x800
+	Green:	0x4000
+)
+
+(TClr.604
+	Red:	0x4000
+	Green:	0x8a00
+)
+
+(TClr.605
+	Red:	0x800
+	Green:	0x4000
+)
+
+(TClr.606
+)
+
+(TClr.607
+)
+
+(TClr.608
+)
+
+(Thresh.609
+)
+
+(GSet.610
+)
+
+(LButn.611
+	HelpTopic:	"New_button"
+	Update:	"Doc.NewUpdate"
+	Label:	"&Neu"
+	Click:	"View.New"
+)
+
+(LButn.612
+	HelpTopic:	"Open_button"
+	Update:	"Doc.OpenUpdate"
+	Label:	"Öffn&en"
+	Click:	"Doc.Open"
+)
+
+(LButn.613
+	HelpTopic:	"Print_button"
+	Update:	"Doc.ActionUpdate"
+	Label:	"D&rucken"
+	Click:	"Doc.Action"
+)
+
+(NameDict.614
+)
+
+(NameDict.615
+	Obj:	616
+	Obj:	617
+)
+
+(AVDict.616
+	InternalName:	"Table of Contents Defaults Dialog"
+)
+
+(AVDict.617
+	InternalName:	"_Thor_"
+)
+
+(FN.1461
+	Path:	"$HOME"
+)
+
+(TClr.1462
+	Red:	0xffff
+	Green:	0xffff
+)
+
+(AVStr.1463
+	S:	"View"
+)
+
+(AVStr.1464
+	S:	"Table"
+)
+
+(AVStr.1465
+	S:	"Chart"
+)
+
+(AVStr.1466
+	S:	"Layout"
+)
+
+(AVStr.1467
+	S:	"Script"
+)
+
+(AVStr.1468
+	S:	"Project"
+)
+
+(AVStr.1469
+	S:	"Appl"
+)
+

Added: packages/thuban/branches/upstream/current/Extensions/importAPR/test/README
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/importAPR/test/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/importAPR/test/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,6 @@
+This directory contains tests of the importAPR extension.
+
+Howto run test (assume thuban source is under ~/project):
+
+export PYTHONPATH=~/project/thuban:~/project/thuban/Lib:~/project/thuban/test
+python test_apr.py

Added: packages/thuban/branches/upstream/current/Extensions/importAPR/test/test_apr.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/importAPR/test/test_apr.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/importAPR/test/test_apr.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,108 @@
+# Copyright (c) 2003 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Tests for APR classes.
+"""
+
+__version__ = "$Revision: 1732 $"
+# $Source$
+# $Id: test_apr.py 1732 2003-09-22 12:22:16Z jan $
+
+import unittest
+
+from Thuban.Model.color import Color, Transparent
+from Thuban.Model.range import Range
+
+from Extensions.importAPR.apr import APR_LClass, APR_TClr
+from Extensions.importAPR.importAPR import ODB
+
+class aprTest(unittest.TestCase):
+
+    def test_TClr(self):
+        """Test the APR_TClr class."""
+        eq = self.assertEquals
+
+        # list with tupels (TClr object, Color object to test against)
+        lst = []
+
+        # a standard RGB TClr object (here: white)
+        obj = APR_TClr(None, 'TClr', 1)
+        setattr(obj, 'Red', '0xffff')
+        setattr(obj, 'Green', '0xffff')
+        setattr(obj, 'Blue', '0xffff')
+        lst.append( (obj, Color(1,1,1)) )
+
+        # an empty TClr object
+        obj = APR_TClr(None, 'TClr', 2)
+        lst.append( (obj, Color(0,0,0)) )
+
+        # an incomplete RGB TClr object (here: only red)
+        obj = APR_TClr(None, 'TClr', 3)
+        setattr(obj, 'Red', '0xffff')
+        lst.append( (obj, Color(1,0,0)) )
+
+        # an incomplete RGB TClr object (here: no full 4 digits of hex-code)
+        obj = APR_TClr(None, 'TClr', 4)
+        setattr(obj, 'Green', '0x0f')
+        obj2 = APR_TClr(None, 'TClr', 5)
+        setattr(obj2, 'Green', '0x0f00')
+        lst.append( (obj, obj2.GetThubanColor()) )
+
+        # a transparent TClr object
+        obj = APR_TClr(None, 'TClr', 6)
+        setattr(obj, 'Name', 'Transparent')
+        lst.append( (obj, Transparent) )
+
+        # finally test all the colors
+        for tclr, color in lst:
+            eq(tclr.GetThubanColor(), color)
+
+    def test_LClass(self):
+        """Test the APR_LClass class."""
+        eq = self.assertEquals
+
+        # list with tupels (TClr object, Color object to test against)
+        lst = []
+
+        # a standard LClass object with numerical range
+        obj = APR_LClass(None, 'LClass', 1)
+        setattr(obj, 'MinNum', '4.00000000000000')
+        setattr(obj, 'MaxNum', '8.00000000000000')
+        setattr(obj, 'Precision', '-3')
+        setattr(obj, 'Label', '3')
+        eq(obj.GetLabel(), '3') # label OK?
+        eq(obj.GetThubanRange().__str__(), Range(']4;8]').__str__()) # range OK?
+
+        # a LClass object with half of the numerical range
+        obj = APR_LClass(None, 'LClass', 1)
+        setattr(obj, 'MaxNum', '8.00000000000000')
+        setattr(obj, 'Precision', '-3')
+        setattr(obj, 'Label', '3')
+        eq(obj.GetLabel(), '3') # label OK?
+        eq(obj.GetThubanRange(), Range(']-oo;8]')) # range OK?
+
+        # a LClass object with a string range describing a single value
+        obj = APR_LClass(None, 'LClass', 1)
+        setattr(obj, 'IsText', '1')
+        setattr(obj, 'MinStr', 'BUILDING')
+        setattr(obj, 'MaxStr', 'BUILDING')
+        setattr(obj, 'Precision', '-3')
+        setattr(obj, 'Label', 'BUILDING')
+        eq(obj.GetLabel(), 'BUILDING') # label OK?
+        eq(obj.GetThubanRange(), 'BUILDING') # range OK?
+
+        # a LClass text object without minstr/maxstr/label
+        obj = APR_LClass(None, 'LClass', 1)
+        setattr(obj, 'IsText', '1')
+        setattr(obj, 'Precision', '-3')
+        eq(obj.GetLabel(), '') # label OK?
+        eq(obj.GetThubanRange(), '') # range OK?
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/Extensions/mouseposition/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/mouseposition/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/mouseposition/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,21 @@
+# Copyright (C) 2005 by Intevation GmbH
+# Authors:
+# Frank Koormann <frank at intevation.de> (2005)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+# import the actual module
+import mouseposition
+
+# perform the registration of the extension
+from Thuban import _
+from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+
+ext_registry.add(ExtensionDesc(
+    name = 'mouseposition',
+    version = '1.0.0',
+    authors= [ 'Frank Koormann' ],
+    copyright = '2005 Intevation GmbH',
+    desc = _("On mouse click display the current coordinates\n" \
+             "in a dialog for easy further processing.")))

Added: packages/thuban/branches/upstream/current/Extensions/mouseposition/mouseposition.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/mouseposition/mouseposition.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/mouseposition/mouseposition.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,119 @@
+# Copyright (C) 2005 by Intevation GmbH
+# Authors:
+# Frank Koormann <frank at intevation.de> (2005)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+xtend thuban with a locator tool.
+
+Collect positions of mouse clicks (in map coordinates) in a text control. 
+
+The tool was implemented in the need to collect some coordinates for some
+work (outside Thuban). The status bar display of the coordinates is quite 
+transient (each mouse movement changes it) and cannot be copied. The tool let 
+one simply collect the coordinates needed and copy them in one block later.
+"""
+
+__version__ = '$Revision: 2721 $'
+# $Source$
+# $Id: mouseposition.py 2721 2007-01-13 15:11:42Z dpinte $
+
+import os, sys
+import string
+
+import wx
+from wx.lib.layoutf import Layoutf
+
+from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
+from Thuban.UI.command import registry, ToolCommand
+from Thuban.UI.mainwindow import main_menu, main_toolbar, \
+                                 make_check_current_tool
+from Thuban.UI.viewport import Tool
+from Thuban.UI.dialogs import NonModalDialog 
+from Thuban import _
+
+import Thuban
+
+class DynamicMessageDialog(NonModalDialog):
+    """Similar to the wx.ScrolledMessageDialog, contents dynamically 
+       changeable by calling applications.
+
+    """
+    def __init__(self, parent, msg, name, caption, pos = wx.DefaultPosition):
+        NonModalDialog.__init__(self, parent, name, caption)
+        x, y = pos
+        if x == -1 and y == -1:
+            self.CenterOnScreen(wx.BOTH)
+        text = wx.TextCtrl(self, -1, msg, wx.DefaultPosition,
+                             wx.DefaultSize,
+                             wx.TE_MULTILINE | wx.TE_READONLY)
+        ok = wx.Button(self, wx.ID_OK, "OK")
+        text.SetConstraints(Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self,ok)))
+        ok.SetConstraints(Layoutf('b=b5#1;x%w50#1;w!80;h!25', (self,)))
+        wx.EVT_BUTTON(self, wx.ID_OK, self.OnClose)
+        self.text = text
+        self.SetAutoLayout(1)
+        self.Layout()
+
+    def getText(self):
+        return self.text.GetValue()
+
+    def setText(self, text):
+        self.text.SetValue(text)
+
+    def appendText(self, text):
+        self.text.AppendText(text)
+
+class MousePositionTool(Tool):
+
+    def __init__(self, view, context):
+        Tool.__init__(self, view)
+        self.context = context
+        self.dlg = None
+
+    def Name(self):
+        return "MousePositionTool"
+
+    def MouseDown(self, event):
+        map_proj = self.view.Map().GetProjection()
+        pos = self.view.CurrentPosition()
+        if pos is not None:
+            pMsg = "%10.10g, %10.10g\n" % pos
+            name = "extension_mouse_position"
+
+            dialog = self.context.mainwindow.get_open_dialog(name)
+            if dialog is None:
+                dialog = DynamicMessageDialog(self.context.mainwindow, 
+                                    pMsg, name, _("Mouse Position Tool"))
+                self.context.mainwindow.add_dialog(name, dialog)
+                dialog.Show(True)
+            else:
+                dialog.appendText(pMsg)
+                dialog.Raise()
+                          
+def mouse_position_tool(context):
+    canvas = context.mainwindow.canvas
+    canvas.SelectTool(MousePositionTool(canvas, context))
+
+
+# locator executed as an tool/extension to Thuban
+iconfile = os.path.join(os.path.abspath(Thuban.__path__[0]),
+                        "..", "Resources", "Bitmaps", "identify")
+iconfile = os.path.join(os.path.abspath(os.path.dirname(__file__)), 
+                        'position')
+registry.Add(ToolCommand("mouse_position_tool", "Mouse Position Tool",
+                 mouse_position_tool, icon = iconfile,
+                 helptext = "Collect mouse click coordinates in a dialog",
+                 checked = make_check_current_tool("MousePositionTool")))
+
+# Add the command to the toolbar
+main_toolbar.InsertSeparator()
+main_toolbar.InsertItem("mouse_position_tool")
+
+# find the extensions menu (create it anew if not found)
+extensions_menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))
+
+# finally add the new entry to the extensions menu
+extensions_menu.InsertItem('mouse_position_tool')

Added: packages/thuban/branches/upstream/current/Extensions/mouseposition/position.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/mouseposition/position.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/mouseposition/position.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,30 @@
+/* XPM */
+static char * position_xpm[] = {
+"24 24 3 1",
+" 	c None",
+".	c #000000",
+"+	c #949194",
+"                        ",
+"                        ",
+"         .              ",
+"   .     ....           ",
+"   .+    .+...  ..      ",
+"   ..    .+.........    ",
+"   ..+   .+...........  ",
+"   ...  ..+...........+ ",
+"   ...+ .+............+ ",
+"   .... .............++ ",
+"   ....+.+ ..........+  ",
+"   ......+  +.......++  ",
+"   .....++    ++....+   ",
+"   ......+       ++++   ",
+"   ......+              ",
+"   .......              ",
+"   ...+...+             ",
+"   ..++....             ",
+"   .++.+++.+            ",
+"    + .+  ++            ",
+"      .+                ",
+"      .+                ",
+"       +                ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Extensions/ogr/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/ogr/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/ogr/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,36 @@
+# Copyright (C) 2004 by Intevation GmbH     vim:encoding=latin-1:
+# Authors:
+# Nina Hüffmeyer <nhueffme at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+__version__ = "$Revision: 2713 $"
+# $Source$
+# $Id: __init__.py 2713 2006-10-26 16:37:42Z bernhard $
+
+# import the actual modules
+from os import environ
+from sys import platform
+
+try:
+    if platform != 'win32':
+        dummy = environ['DISPLAY']
+    import ogrstart
+except KeyError:
+    pass # For non-win32 platform, we don't have a DISPLAY, so don't import 
+         # the modules (for test mode)
+         # For win32 platform, there is  always have a graphical mode
+         # Not sure whether this is the best method to avoid problems
+         # in the global test routine.
+
+# perform the registration of the extension
+from Thuban import _, internal_from_unicode
+from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+
+ext_registry.add(ExtensionDesc(
+    name = 'OGRstart',
+    version = '0.9.0',
+    authors= [ internal_from_unicode(u'Nina H\xfcffmeyer') ],
+    copyright = '2004 Intevation GmbH',
+    desc = _("Open a file supported by ogr.")))

Added: packages/thuban/branches/upstream/current/Extensions/ogr/ogrdialog.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/ogr/ogrdialog.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/ogr/ogrdialog.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,416 @@
+# Copyright (c) 2001, 2003, 2004 by Intevation GmbH     vim:encoding=latin-1:
+# Authors:
+# Martin Müller <mmueller at intevation.de>
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+
+"""Dialogs to manage database connections"""
+
+import sys, traceback
+
+import wx
+
+try:
+    import ogr
+except ImportError:
+    ogr = None
+
+from Thuban import _
+from Thuban.Model.table import FIELDTYPE_INT
+from Extensions.ogr import ogrshapes
+
+
+ID_DBCHOOSE_RETRIEVE = 9201
+ID_DBCHOOSE_OK       = 9202
+ID_DBCHOOSE_CANCEL   = 9203
+ID_LB_DCLICK         = 9204
+
+
+class ChooseFileFormat(wx.Dialog):
+    """This dialog lists all available drivers.
+    """
+    def __init__(self, parent, session):
+        """Initialize the dialog.
+        """
+        wx.Dialog.__init__(self, parent, -1, _("Choose file format"),
+                          style = wx.DIALOG_MODAL|wx.CAPTION)
+        self.session = session
+        self.tables = []
+
+        #
+        # Build the dialog
+        #
+
+        # Sizer for the entire dialog
+        top = wx.FlexGridSizer(2, 1, 0, 0)
+
+        # Sizer for the main part with the list box
+        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+        top.Add(main_sizer, 1, wx.EXPAND, 0)
+
+        # The list box with the drivers
+        static_box = wx.StaticBoxSizer(wx.StaticBox(self, -1, "File formats"),
+                                   wx.HORIZONTAL)
+        self.lb_drivers = wx.ListBox(self, -1)
+        static_box.Add(self.lb_drivers, 0, wx.EXPAND, 0)
+        main_sizer.Add(static_box, 1, wx.EXPAND, 0)
+
+        for i in range(ogr.GetDriverCount()):
+            self.lb_drivers.Append(ogr.GetDriver(i).GetName())
+        if self.lb_drivers.GetCount() > 0:
+            self.lb_drivers.SetSelection(0, True)
+
+        # The standard button box at the bottom of the dialog
+        buttons = wx.FlexGridSizer(1, 2, 0, 0)
+        ok_button = wx.Button(self, ID_DBCHOOSE_OK, _("OK"))
+        wx.EVT_BUTTON(self, ID_DBCHOOSE_OK, self.OnOK)
+        buttons.Add(ok_button, 0, wx.ALL|wx.ALIGN_RIGHT, 4)
+        cancel_button = wx.Button(self, ID_DBCHOOSE_CANCEL, _("Cancel"))
+        wx.EVT_BUTTON(self, ID_DBCHOOSE_CANCEL, self.OnCancel)
+        buttons.Add(cancel_button, 0, wx.ALL, 4)
+        top.Add(buttons, 1, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 4)
+
+        # Autosizing
+        self.SetAutoLayout(1)
+        self.SetSizer(top)
+        top.Fit(self)
+        top.SetSizeHints(self)
+        self.Layout()
+
+
+    def GetTable(self):
+        """no functionality
+        """
+        return None
+
+    def OnLBDClick(self, event):
+        """Close dialog.
+        """
+        if self.lb_tables.GetSelection() >= 0:
+            self.EndModal(wx.ID_OK)
+            self.Show(False)
+
+    def OnOK(self, event):
+        """Close dialog.
+        """
+        self.EndModal(wx.ID_OK)
+        self.Show(False)
+
+    def OnCancel(self, event):
+        """Close dialog.
+        """
+        self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+
+class ChooseLayer(wx.Dialog):
+    """This dialog lists all the layers contained in the given datasource.
+
+    One layer can be chosen, which is then opened.
+    """
+
+    def __init__(self, parent, filename):
+        """Initialize the dialog.
+        """
+        wx.Dialog.__init__(self, parent, -1, _("Choose layer"),
+                          style = wx.DIALOG_MODAL|wx.CAPTION)
+        self.tables = []
+
+        #
+        # Build the dialog
+        #
+
+        # Sizer for the entire dialog
+        top = wx.FlexGridSizer(2, 1, 0, 0)
+
+        # Sizer for the main part with the list boxes
+        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+        top.Add(main_sizer, 1, wx.EXPAND, 0)
+
+        # The list box with the drivers
+        static_box = wx.StaticBoxSizer(wx.StaticBox(self, -1, _("Layers")),
+                                   wx.HORIZONTAL)
+        self.lb_drivers = wx.ListBox(self, -1)
+        static_box.Add(self.lb_drivers, 0, wx.EXPAND, 0)
+        main_sizer.Add(static_box, 1, wx.EXPAND, 0)
+
+        datasource = ogr.Open(filename)
+        self.layer = []
+        for i in range(datasource.GetLayerCount()):
+            self.layer.append(datasource.GetLayer(i))
+            self.lb_drivers.Append(datasource.GetLayer(i).GetName())
+        if self.lb_drivers.GetCount() > 0:
+            self.lb_drivers.SetSelection(0, True)
+
+        # The standard button box at the bottom of the dialog
+        buttons = wx.FlexGridSizer(1, 2, 0, 0)
+        ok_button = wx.Button(self, ID_DBCHOOSE_OK, _("OK"))
+        wx.EVT_BUTTON(self, ID_DBCHOOSE_OK, self.OnOK)
+        buttons.Add(ok_button, 0, wx.ALL|wx.ALIGN_RIGHT, 4)
+        cancel_button = wx.Button(self, ID_DBCHOOSE_CANCEL, _("Cancel"))
+        wx.EVT_BUTTON(self, ID_DBCHOOSE_CANCEL, self.OnCancel)
+        buttons.Add(cancel_button, 0, wx.ALL, 4)
+        top.Add(buttons, 1, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 4)
+
+        # Autosizing
+        self.SetAutoLayout(1)
+        self.SetSizer(top)
+        top.Fit(self)
+        top.SetSizeHints(self)
+        self.Layout()
+
+    def end_dialog(self, result):
+        """If the dialog is closed with OK, set chosen layer as layer 
+        to be opened.
+        """
+        self.result = result
+        if result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        """Dialog closed with OK button.
+        """
+        self.end_dialog(self.lb_drivers.GetSelection())
+
+    def OnCancel(self, event):
+        """Dialog closed with Cancel.
+        """
+        self.end_dialog(None)
+
+    def GetLayer(self):
+        """Return the selected layer."""
+        return self.layer[self.lb_drivers.GetSelection()].GetName()
+
+
+class ChooseOGRDBTableDialog(wx.Dialog):
+    """This dialog opens a datasource from an existing database connection.
+
+    A list of all available database connections is offered. If one connection
+    is selected and the button "Retrieve" is clicked, all layers are listed.
+    One of these layers can be chosen to be opened.
+    An ID column can be chosen, too."""
+
+    def __init__(self, parent, session):
+        """Initialize the dialog.
+        """
+        wx.Dialog.__init__(self, parent, -1, _("Choose layer from database"),
+                          style = wx.DIALOG_MODAL|wx.CAPTION)
+        self.session = session
+        self.dbconns = self.session.DBConnections()
+        self.tables = []
+
+        #
+        # Build the dialog
+        #
+
+        # Sizer for the entire dialog
+        top = wx.FlexGridSizer(2, 1, 0, 0)
+
+        # Sizer for the main part with the list boxes
+        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+        top.Add(main_sizer, 1, wx.EXPAND, 0)
+
+        # The list box with the connections
+        static_box = wx.StaticBoxSizer(wx.StaticBox(self, -1, _("Databases")),
+                                   wx.HORIZONTAL)
+        self.lb_connections = wx.ListBox(self, -1)
+        static_box.Add(self.lb_connections, 0, wx.EXPAND, 0)
+        main_sizer.Add(static_box, 1, wx.EXPAND, 0)
+
+        for i in range(len(self.dbconns)):
+            self.lb_connections.Append(self.dbconns[i].BriefDescription())
+        if self.lb_connections.GetCount() > 0:
+            self.lb_connections.SetSelection(0, True)
+
+        # The button box between the connections list box and the table
+        # list box
+        buttons = wx.FlexGridSizer(3, 1, 0, 0)
+        buttons.Add(20, 80, 0, wx.EXPAND, 0)
+        retrieve_button = wx.Button(self, ID_DBCHOOSE_RETRIEVE, _("Retrieve"))
+        wx.EVT_BUTTON(self, ID_DBCHOOSE_RETRIEVE, self.OnRetrieve)
+        buttons.Add(retrieve_button, 0, wx.ALL
+                    |wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 4)
+        buttons.Add(20, 80, 0, wx.EXPAND, 0)
+        main_sizer.Add(buttons, 0, wx.EXPAND, 0)
+
+        # The list box with the tables
+        static_box = wx.StaticBoxSizer(wx.StaticBox(self, -1, _("Tables")),
+                                   wx.HORIZONTAL)
+        self.lb_tables = wx.ListBox(self, ID_LB_DCLICK)
+        wx.EVT_LISTBOX(self, ID_LB_DCLICK, self.OnTableSelect)
+        wx.EVT_LISTBOX_DCLICK(self, ID_LB_DCLICK, self.OnLBDClick)
+        static_box.Add(self.lb_tables, 0, wx.EXPAND, 0)
+        main_sizer.Add(static_box, 1, wx.EXPAND, 0)
+
+        # id column and geometry column selection
+        box = wx.BoxSizer(wx.VERTICAL)
+        box.Add(wx.StaticText(self, -1, _("ID Column")), 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.text_id_column = wx.ComboBox(self, -1, "")
+        box.Add(self.text_id_column, 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 4)
+        main_sizer.Add(box, 1, wx.EXPAND, 0)
+
+        # The standard button box at the bottom of the dialog
+        buttons = wx.FlexGridSizer(1, 2, 0, 0)
+        ok_button = wx.Button(self, ID_DBCHOOSE_OK, _("OK"))
+        wx.EVT_BUTTON(self, ID_DBCHOOSE_OK, self.OnOK)
+        buttons.Add(ok_button, 0, wx.ALL|wx.ALIGN_RIGHT, 4)
+        cancel_button = wx.Button(self, ID_DBCHOOSE_CANCEL, _("Cancel"))
+        wx.EVT_BUTTON(self, ID_DBCHOOSE_CANCEL, self.OnCancel)
+        buttons.Add(cancel_button, 0, wx.ALL, 4)
+        top.Add(buttons, 1, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 4)
+
+        # Autosizing
+        self.SetAutoLayout(1)
+        self.SetSizer(top)
+        top.Fit(self)
+        top.SetSizeHints(self)
+        self.Layout()
+
+
+    def GetTable(self):
+        """Return the chosen DB connection, the table to be opened, 
+        the connection string for ogr and the ID column.
+        """
+        i = self.lb_tables.GetSelection()
+        if i >= 0:
+            return (self.selected_conn, self.connString, self.tables[i],
+                    self.text_id_column.GetValue())
+        return None
+
+    def OnRetrieve(self, event):
+        """Provide a list of all available layers in the selected datasource.
+        """
+        i = self.lb_connections.GetSelection()
+        if i >= 0:
+            self.selected_conn = self.dbconns[i]
+            self.connString = "PG: dbname=%s" %self.selected_conn.dbname
+            if self.selected_conn.host is not "":
+                self.connString = (self.connString + " host=%s"
+                                    %self.selected_conn.host)
+            if self.selected_conn.user is not "":
+                self.connString = (self.connString + " user=%s"
+                                    %self.selected_conn.user)
+            if self.selected_conn.password is not "":
+                self.connString = (self.connString + " password=%s"
+                                    %self.selected_conn.password)
+            if self.selected_conn.port is not "":
+                self.connString = (self.connString + " port= %s"
+                                    %self.selected_conn.port)
+            ds = ogr.Open(self.connString)
+            if ds:
+                for i in range(ds.GetLayerCount()):
+                    self.tables.append(ds.GetLayer(i).GetName())
+                self.lb_tables.Set(self.tables)
+
+    def OnTableSelect(self, event):
+        """If a table is selected, list all possible ID columns.
+        """
+        i = self.lb_tables.GetSelection()
+        self.text_id_column.Clear()
+        if i >= 0:
+            for name, typ in self.selected_conn.table_columns(self.tables[i]):
+                if typ == FIELDTYPE_INT:
+                    self.text_id_column.Append(name)
+
+    def OnLBDClick(self, event):
+        """Close dialog.
+        """
+        if self.lb_tables.GetSelection() >= 0:
+            self.EndModal(wx.ID_OK)
+            self.Show(False)
+
+    def OnOK(self, event):
+        """Dialog closed with OK button.
+        """
+        self.EndModal(wx.ID_OK)
+        self.Show(False)
+
+    def OnCancel(self, event):
+        """Dialog closed with Cancel.
+        """
+        self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+
+class OGRConnectionDialog(wx.Dialog):
+    """A string can be enteres, which is directly passed to ogr to open a
+    datasource.
+    """
+    def __init__(self, parent, session):
+        """Initialize the dialog.
+        """
+        wx.Dialog.__init__(self, parent, -1, "Enter string for OGRConnection",
+                          style = wx.DIALOG_MODAL|wx.CAPTION)
+        self.session = session
+
+        # Sizer for the entire dialog
+        top = wx.BoxSizer(wx.VERTICAL)
+
+        # The list box with the drivers
+        box = wx.BoxSizer(wx.HORIZONTAL)#wx.Box(self, -1, _("OGRConnection")),
+                            #       wx.HORIZONTAL)
+        box.Add(wx.StaticText(self, -1, _("URL:")), 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.text_string = wx.TextCtrl(self, -1, "")
+        box.Add(self.text_string, 0, wx.EXPAND, 0)
+        top.Add(box, 0, wx.EXPAND)
+
+        # The standard button box at the bottom of the dialog
+        buttons = wx.FlexGridSizer(1, 2, 0, 0)
+        ok_button = wx.Button(self, ID_DBCHOOSE_OK, _("OK"))
+        wx.EVT_BUTTON(self, ID_DBCHOOSE_OK, self.OnOK)
+        buttons.Add(ok_button, 0, wx.ALL|wx.ALIGN_RIGHT, 4)
+        cancel_button = wx.Button(self, ID_DBCHOOSE_CANCEL, _("Cancel"))
+        wx.EVT_BUTTON(self, ID_DBCHOOSE_CANCEL, self.OnCancel)
+        buttons.Add(cancel_button, 0, wx.ALL, 4)
+        top.Add(buttons, 1, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 4)
+
+        # Autosizing
+        self.SetAutoLayout(1)
+        self.SetSizer(top)
+        top.Fit(self)
+        top.SetSizeHints(self)
+        self.Layout()
+
+    def RunDialog(self):
+        """Run dialog
+        """
+        self.ShowModal()
+        self.Destroy()
+        return self.result
+
+    def end_dialog(self, result):
+        """Close dialog
+        """
+        self.result = result
+        if result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        """Dialog closed with OK
+        """
+        result = {}
+        result["string"] = getattr(self, "text_string").GetValue()
+        self.end_dialog(result)
+
+    def OnCancel(self, event):
+        """Dialog closed with Cancel.
+        """
+        self.end_dialog(None)
+
+    def GetDatasourceName(self):
+        """Return the string to be used for opening the database
+        """
+        return self.result["string"]
+

Added: packages/thuban/branches/upstream/current/Extensions/ogr/ogrshapes.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/ogr/ogrshapes.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/ogr/ogrshapes.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,853 @@
+# Copyright (C) 2004 by Intevation GmbH     vim:encoding=latin-1:
+# Authors:
+# Nina Hüffmeyer <nhueffme at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+__version__ = "$Revision: 2713 $"
+# $Source$
+# $Id: ogrshapes.py 2713 2006-10-26 16:37:42Z bernhard $
+
+from __future__ import generators
+
+try:
+    import ogr
+except ImportError:
+    ogr = None
+
+import os
+
+from Thuban import _
+from Thuban.Model import table
+from Thuban.Model import transientdb
+from Thuban.Model.transientdb import  TransientDatabase
+
+from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
+from Thuban.Model.data import RAW_PYTHON, RAW_SHAPEFILE, RAW_WKT
+from Thuban.Model.data import FileShapeStore
+
+def has_ogr_support():
+    """Return whether this Thuban instance supports ogr file formats
+
+    Having OGR support means that the ogr module can be
+    imported.
+    """
+    return ogr is not None
+
+if ogr is not None:
+    SHAPETYPE_UNKNOWN = ogr.wkbUnknown
+    SHAPETYPE_GEOMCOLL = ogr.wkbGeometryCollection
+    SHAPETYPE_NONE = ogr.wkbNone
+
+    # mapping from ogr-lib shapetypes and table constants to our constants
+    ogrlib_shapetypes = {ogr.wkbPolygon: SHAPETYPE_POLYGON,
+                ogr.wkbLineString: SHAPETYPE_ARC,
+                ogr.wkbPoint: SHAPETYPE_POINT,
+                ogr.wkbUnknown: SHAPETYPE_UNKNOWN,
+                ogr.wkbNone: SHAPETYPE_NONE,
+                ogr.wkbGeometryCollection: SHAPETYPE_GEOMCOLL}
+
+    fieldtype_map = {ogr.OFTString: table.FIELDTYPE_STRING,
+                ogr.OFTInteger: table.FIELDTYPE_INT,
+                ogr.OFTReal: table.FIELDTYPE_DOUBLE}
+
+else:
+    ogrlib_shapetypes = {}
+    fieldtype_map = {}
+    SHAPETYPE_UNKNOWN = 0
+    SHAPETYPE_GEOMCOLL = 7
+    SHAPETYPE_NONE = 100
+
+
+class OGRShape:
+    """Represent one shape of an OGRShapeStore
+    """
+
+    def __init__(self, shapestore, shape):
+        """Initialize the shape object.
+
+        shapestore should be an instance of OGRShapeStore,
+        shape should be an instance of an OGRFeature.
+        """
+        self.ogrlayer = shapestore.ogrlayer
+        id_column = shapestore.Id_column()
+        self.feature = shape
+        if id_column is None:
+            self.shapeid = self.feature.GetFID()
+        else:
+            self.shapeid = self.feature.GetField(id_column)
+        self.geom = self.feature.GetGeometryRef()
+        if self.geom:
+            self.shapetype = self.geom.GetGeometryType()
+            self.bbox = self._compute_bbox()
+            self.points = self._points()
+        else:
+            self.shapetype = ogr.wkbNone
+            self.bbox = None
+            self.points = [[]]
+        try:
+            self.shapetype = ogrlib_shapetypes[self.shapetype]
+        except:
+            self.shapetype = ogrlib_shapetypes[ogr.wkbUnknown]
+
+        self.geoms = self._geoms()
+
+    def _geoms(self):
+        """Return a list of geometry objects.
+
+        If the shape is a geometry collection, all contained geometry
+        objects are stored to the list as OGRGeometry objects.
+        """
+        geoms = []
+        if self.shapetype == SHAPETYPE_GEOMCOLL:
+            for i in range(self.geom.GetGeometryCount()):
+                geoms.append(OGRGeometry(self, self.geom, i))
+        return geoms
+
+    def _compute_bbox(self):
+        """
+        Compute the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
+        """
+        minx, maxx, miny, maxy = self.geom.GetEnvelope()
+        return (minx, miny, maxx, maxy)
+
+    def compute_bbox(self):
+        """
+        Return the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
+        """
+        return self.bbox
+
+    def ShapeID(self):
+        """Return the feature id of this shape.
+        """
+        return self.shapeid
+
+    def Points(self):
+        """Return the coordinates of the shape as a list of lists of pairs
+        """
+        return self.points
+
+    def _points(self):
+        """Get the coordinates of the shape as a list of lists of pairs
+        """
+        shape = []
+
+        if self.geom is None:
+            return shape.append([])
+
+        # if geometry object is of type point or line
+        if self.geom.GetGeometryCount() == 0:
+            points =[]
+            for point in range(self.geom.GetPointCount()):
+                x = self.geom.GetX(point)
+                y = self.geom.GetY(point)
+                points.append((x, y))
+            return [points]
+        # if geometry object is of type polygon or multipolygon
+        for i in range(self.geom.GetGeometryCount()):
+            points = []
+            geometry = self.geom.GetGeometryRef(i)
+            # if geometry object is polygon
+            if geometry.GetGeometryCount() == 0:
+                for point in range(geometry.GetPointCount()):
+                    x = geometry.GetX(point)
+                    y = geometry.GetY(point)
+                    points.append((x, y))
+                shape.append(points)
+            # if geometry object is of type multipolygon or geometry collection
+            else:
+                for j in range(geometry.GetGeometryCount()):
+                    points = []
+                    subgeom = geometry.GetGeometryRef(j)
+                    for point in range(subgeom.GetPointCount()):
+                        x = subgeom.GetX(point)
+                        y = subgeom.GetY(point)
+                        points.append((x, y))
+                    shape.append(points)
+        return shape
+
+    def RawData(self):
+        """Return the shape id to use with the shapestore
+        """
+        return self.shapeid
+
+    def OGRLayer(self):
+        """Return the ogrlayer object
+        """
+        return self.ogrlayer
+
+    def ShapeType(self):
+        """Return the shapetype of this shape (may differ from the layer's
+        shapetype)
+        """
+        return self.shapetype
+
+    def GetGeoms(self):
+        """Return the list of geometries of this feature.
+
+        If this feature is a geometry collection, all contained geometries
+        are given. Else the returned list is empty.
+        """
+        return self.geoms
+
+    def GetGeom(self, index):
+        """Return the OGRGeometry object at the specified index.
+
+        This is not none only if the shape is a geometry collection.
+        """
+        if index < len(self.geoms):
+            return self.geoms[index]
+        else:
+            return None
+
+
+class OGRGeometry:
+    """This class represents a geometry belonging to a specified feature.
+    """
+
+    def __init__(self, shape, geom, index):
+        """Initialize the geometry object.
+
+        shape should be an OGRShape, which this geometry belongs to.
+        geom is the base geometry, index is the ReferenceID.
+        """
+        self.shape = shape
+        self.index = index
+
+        self.geom = geom.GetGeometryRef(index)
+        try:
+            self.shapetype = ogrlib_shapetypes[self.geom.GetGeometryType()]
+        except:
+            self.shapetype = ogrlib_shapetypes[ogr.wkbUnknown]
+
+
+    def ShapeType(self):
+        """Return the shapetype of this geometry object."""
+        return self.shapetype
+
+
+class OGRShapeStore:
+    """Corresponds to an OGRLayer object, containing features/shapes and
+       providing the same methods like ShapefileStore.
+
+       In fact, for all file based shape stores, the class OGRFileShapeStore
+       should be used. Only database shape stores should be
+       used with OGRShapeStore. It is subject to re-factoring
+       to end up with better class names and sensible base classes.
+    """
+
+    # TODO: re-factor this class to be not responsible for file-based
+    # stores anymore.
+
+    def __init__(self, session, filename, layername, id_column = None):
+        """Initialize the shapestore.
+
+        All required information is loaded from the datasource.
+        """
+        # if id_column is None, data is loaded from file, so we need path
+        # if id_column is not None, data is loaded from database
+        if id_column is None:
+            self.filename = os.path.abspath(filename)
+        else:
+            self.filename = filename
+        self.layername = layername
+
+        self.ogrdatasource = ogr.Open(filename)
+        self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)
+
+        if id_column is not None:
+            self.id_column = id_column
+        else:
+            self.id_column = None
+
+        self.table = OGRTable(session, self.ogrdatasource, self.ogrlayer,
+                                self.id_column)
+
+        self._open_ogrlayer(layername)
+
+    def _open_ogrlayer(self, layername):
+        """Get all required information from the datasource.
+        """
+        self.numshapes = self.ogrlayer.GetFeatureCount()
+        self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()
+
+        extent = self.ogrlayer.GetExtent()
+        if extent:
+            self.bbox = [extent[0], extent[2], extent[1], extent[3]]
+        else:
+            self.bbox = None
+
+        try:
+            self.shapetype = ogrlib_shapetypes[self.shapetype]
+        except:
+            # if shapetype is not contained in ogrlib_shapetypes
+            # treat it like SHAPETYPE_UNKNOWN
+            self.shapetype = ogrlib_shapetypes[ogr.wkbUnknown]
+
+        self.shapes = self.shapes()
+
+    def shapes(self):
+        """Return a collection of all features as OGRShape objects.
+        """
+        shapes = {}
+        self.ogrlayer.ResetReading()
+        if self.id_column is None:
+            nextFeature = self.ogrlayer.GetNextFeature()
+            while nextFeature is not None:
+                fid = nextFeature.GetFID()
+                shape = OGRShape(self, nextFeature)
+                shapes[shape.ShapeID()] = shape
+                nextFeature = self.ogrlayer.GetNextFeature()
+        else:
+            lay = self.ogrdatasource.ExecuteSQL("SELECT %s, * from %s" 
+                                    % (self.id_column, self.layername))
+            if lay is not None:
+                lay.ResetReading()
+                nextFeature = lay.GetNextFeature()
+                while nextFeature is not None:
+                    fid = nextFeature.GetField(0)
+                    shape = OGRShape(self, nextFeature)
+                    shapes[shape.ShapeID()] = shape
+                    nextFeature = lay.GetNextFeature()
+                self.ogrdatasource.ReleaseResultSet(lay)
+        return shapes
+
+    def OGRLayer(self):
+        """Return the OGRLayer object
+        """
+        return self.ogrlayer
+
+    def FileName(self):
+        """Return the filename used to open the file
+        """
+        return self.filename
+
+    def FileType(self):
+        """Return the filetype. This is depending on the driver used to open
+        the file.
+        """
+        return self.ogrdatasource.GetDriver().GetName()
+
+    def ShapeType(self):
+        """Return the type of the shapes in the shapestore.
+
+        This is either SHAPETYPE_POINT, SHAPETYPE_ARC, SHAPETYPE_POLYGON,
+        SHAEPTYPE_GEOMCOLL, SHAPETYPE_NONE or SHAPETYPE_UNKNOWN.
+        """
+        return self.shapetype
+
+    def RawShapeFormat(self):
+        """Return the raw data format of the shape data, i.e. RAW_PYTHON
+        """
+        return RAW_PYTHON
+
+    def NumShapes(self):
+        """Return the number of shapes in the shape store
+        """
+        return self.numshapes
+
+    def BoundingBox(self):
+        """Return the bounding box of the shapes in the shapestore.
+        """
+        return self.bbox
+
+    def ShapesInRegion(self, bbox):
+        """Return an iterable over the shapes that overlap the bounding box.
+
+        The bbox parameter should be the bounding box as a tuple in the
+        form (minx, miny, maxx, maxy) in the coordinate system of the
+        shape store.
+        """
+        left, bottom, right, top = bbox
+
+        # create a geometry which can be passed to the layer as spatial filter
+        bboxpolygon = ogr.CreateGeometryFromWkt(
+                      ('Polygon((%s %s, %s %s, %s %s,%s %s, %s %s))'
+                                 %(left, bottom, left, top, right, top,
+                                  right, bottom, left, bottom)))
+
+        if self.ogrlayer.GetSpatialRef():
+            bboxpolygon.AssignSpatialReference(self.ogrlayer.GetSpatialRef())
+
+        self.ogrlayer.ResetReading()
+        #ogrlayer.SetSpatialFilterRect(left, bottom, right, top)
+        self.ogrlayer.SetSpatialFilter(bboxpolygon)
+
+        numFeatures = self.ogrlayer.GetFeatureCount()
+        # if no features are in bbox, return all features as shapesInRegion
+        # (PostGIS sometimes returns no features even if they are within 
+        #  the bounding box)
+        if numFeatures == 0:
+            self.ogrlayer.SetSpatialFilter(None)
+            numFeatures = self.ogrlayer.GetFeatureCount()
+        for feature in range(numFeatures):
+            nextFeature = self.ogrlayer.GetNextFeature()
+            if self.id_column is None:
+                yield self.shapes[nextFeature.GetFID()]
+            else:
+                yield self.shapes[nextFeature.GetField(self.id_column)]
+
+        self.ogrlayer.SetSpatialFilter(None)
+        bboxpolygon.Destroy()
+
+    def AllShapes(self):
+        """Return an iterable over the shapes in the shape store.
+        """
+        for id in range(len(self.shapes)):
+            yield self.shapes[id]
+
+    def Shape(self, fid):
+        """Return the shape with fid = fid
+        """
+        if fid in self.table.ids.keys():
+            return self.shapes[fid]
+        else:
+            return None
+
+    def Table(self):
+        """Return the table containing the attribute data
+        """
+        return self.table
+
+    def Dependencies(self):
+        """Return the empty tuple.
+        """
+        return ()
+
+    def OrigShapeStore(self):
+        """Return None."""
+        return None
+
+    def Id_column(self):
+        """Return the id_column.
+        """
+        return self.id_column
+
+class OGRFileShapeStore(FileShapeStore):
+    """Corresponds to an OGRLayer object, containing features/shapes and
+       providing the same methods like ShapefileStore.
+    """
+
+    def __init__(self, session, filename, layername, id_column = None):
+        """Initialize the shapestore.
+
+        All required information is loaded from the datasource.
+        """
+        self._bbox = None
+        self.ogrdatasource = ogr.Open(filename)
+
+        # filetype is depending on the driver used to open the file.
+        self._filetype = self.ogrdatasource.GetDriver().GetName()
+        if self._filetype == 'ESRI Shapefile':
+            self._filetype = "shapefile"
+        FileShapeStore.__init__(self, filename,
+                                sublayer_name = layername)
+
+        self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)
+
+        self._table = OGRTable(session, self.ogrdatasource, self.ogrlayer,
+                               id_column)
+
+        self._open_ogrlayer(layername)
+
+    def _open_ogrlayer(self, layername):
+        """Get all required information from the datasource.
+        """
+        self.numshapes = self.ogrlayer.GetFeatureCount()
+        self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()
+
+        extent = self.ogrlayer.GetExtent()
+        if extent:
+            self._bbox = [extent[0], extent[2], extent[1], extent[3]]
+        else:
+            self._bbox = None
+
+        try:
+            self.shapetype = ogrlib_shapetypes[self.shapetype]
+        except:
+            # if shapetype is not contained in ogrlib_shapetypes
+            # treat it like SHAPETYPE_UNKNOWN
+            self.shapetype = ogrlib_shapetypes[ogr.wkbUnknown]
+
+        self.shapes = self.shapes()
+
+    def FileType(self):
+        """Return the filetype."""
+        return self._filetype
+
+    def BoundingBox(self):
+        """Return the bounding box of the shapes in the shape file.
+
+        The coordinate system used is whatever was used in the shape file.
+        If the shape file is empty, return None.
+        """
+        return self._bbox
+
+    def shapes(self):
+        """Return a collection of all features as OGRShape objects.
+        """
+        shapes = {}
+        self.ogrlayer.ResetReading()
+
+        nextFeature = self.ogrlayer.GetNextFeature()
+        while nextFeature is not None:
+            fid = nextFeature.GetFID()
+            shape = OGRShape(self, nextFeature)
+            shapes[shape.ShapeID()] = shape
+            nextFeature = self.ogrlayer.GetNextFeature()
+
+        return shapes
+
+    def OGRLayer(self):
+        """Return the OGRLayer object
+        """
+        return self.ogrlayer
+
+    def ShapeType(self):
+        """Return the type of the shapes in the shapestore.
+
+        This is either SHAPETYPE_POINT, SHAPETYPE_ARC, SHAPETYPE_POLYGON,
+        SHAEPTYPE_GEOMCOLL, SHAPETYPE_NONE or SHAPETYPE_UNKNOWN.
+        """
+        return self.shapetype
+
+    def RawShapeFormat(self):
+        """Return the raw data format of the shape data, i.e. RAW_PYTHON
+        """
+        return RAW_PYTHON
+
+    def NumShapes(self):
+        """Return the number of shapes in the shape store
+        """
+        return self.numshapes
+
+    def ShapesInRegion(self, bbox):
+        """Return an iterable over the shapes that overlap the bounding box.
+
+        The bbox parameter should be the bounding box as a tuple in the
+        form (minx, miny, maxx, maxy) in the coordinate system of the
+        shape store.
+        """
+        left, bottom, right, top = bbox
+
+        # create a geometry which can be passed to the layer as spatial filter
+        bboxpolygon = ogr.CreateGeometryFromWkt(
+                      ('Polygon((%s %s, %s %s, %s %s,%s %s, %s %s))'
+                                 %(left, bottom, left, top, right, top,
+                                  right, bottom, left, bottom)))
+
+        if self.ogrlayer.GetSpatialRef():
+            bboxpolygon.AssignSpatialReference(self.ogrlayer.GetSpatialRef())
+
+        self.ogrlayer.ResetReading()
+        #ogrlayer.SetSpatialFilterRect(left, bottom, right, top)
+        self.ogrlayer.SetSpatialFilter(bboxpolygon)
+
+        numFeatures = self.ogrlayer.GetFeatureCount()
+        # if no features are in bbox, return all features as shapesInRegion
+        # (PostGIS sometimes returns no features even if they are within 
+        #  the bounding box)
+        if numFeatures == 0:
+            self.ogrlayer.SetSpatialFilter(None)
+            numFeatures = self.ogrlayer.GetFeatureCount()
+        for feature in range(numFeatures):
+            nextFeature = self.ogrlayer.GetNextFeature()
+            yield self.shapes[nextFeature.GetFID()]
+
+        self.ogrlayer.SetSpatialFilter(None)
+        bboxpolygon.Destroy()
+
+    def AllShapes(self):
+        """Return an iterable over the shapes in the shape store.
+        """
+        for id in range(len(self.shapes)):
+            yield self.shapes[id]
+
+    def Shape(self, fid):
+        """Return the shape with fid = fid
+        """
+        if fid in self.Table().ids.keys():
+            return self.shapes[fid]
+        else:
+            return None
+
+    def Table(self):
+        """Return the table containing the attribute data."""
+        return self._table
+
+    def Dependencies(self):
+        """Return the empty tuple.
+        """
+        return ()
+
+    def OrigShapeStore(self):
+        """Return None."""
+        return None
+
+    def Id_column(self):
+        """Return the id_column.
+        """
+        return None
+
+class OGRTable(transientdb.AutoTransientTable):
+    """A Table for an ogr datasource.
+    """
+
+    def __init__(self, session, ds, layer, id_column):
+        """Initialize the OGRTable.
+
+        session   - should be the current session.
+        ds        - should be an instance of OGRDatasource.
+        layer     - should be an instance of OGRLayer.
+        id_column - should be the name of the column used as ID column
+        """
+        self.datasource = ds
+        self.layer = layer
+        self.tablename = self.layer.GetName()
+        self.id_column = id_column
+
+        # Map column names and indices to column objects.
+        self.column_map = {}
+
+        # Map feature ids to ordinals.
+        self._map_ords_and_ids()
+
+        self._fetch_table_information()
+        self._fetch_table_content()
+
+        transientdb.AutoTransientTable.__init__(self, session.TransientDB(),
+                                                self)
+
+    def _fetch_table_information(self):
+        """Internal: Update information about the table
+        """
+        self.columns = []
+
+        layerdefn = self.layer.GetLayerDefn()
+        # if FID column is of interest
+        #col = OGRColumn("FID", table.FIELDTYPE_INT, layerdefn.GetFieldCount())
+        #self.columns.append(col)
+        for i in range(layerdefn.GetFieldCount()):
+            fielddef = layerdefn.GetFieldDefn(i)
+            fieldname = fielddef.GetName()
+            fieldtype = fieldtype_map[fielddef.GetType()]
+            fieldindex = layerdefn.GetFieldIndex(fieldname)
+            col = OGRColumn(fieldname, fieldtype, fieldindex)
+            if col is not None:
+                self.columns.append(col)
+
+        for col in self.columns:
+            self.column_map[col.name] = col
+            self.column_map[col.index] = col
+
+    def _fetch_table_content(self):
+        """Internal: Update information contained in the table
+        """
+        self.content = []
+        layerdefn = self.layer.GetLayerDefn()
+
+        self.layer.ResetReading()
+        for i in range(self.layer.GetFeatureCount()):
+            nextFeature = self.layer.GetNextFeature()
+            row = []
+            for j in range(layerdefn.GetFieldCount()):
+                row.append(nextFeature.GetField(j))
+            # if FID should be listed in the table
+            #if self.id_column is None:
+            #    row.append(nextFeature.GetFID())
+            #else:
+            #    row.append(nextFeature.GetField(self.id_column))
+            self.content.append(row)
+
+    def _map_ords_and_ids(self):
+        """Create collections which map ordinals to ids and verse visa.
+        """
+        self.ordinals = {}
+        self.ids = {}
+
+        if self.id_column is not None:
+            lay = self.datasource.ExecuteSQL("SELECT %s from %s"
+                    %(self.id_column, self.tablename))
+            lay.ResetReading()
+            nextFeature = lay.GetNextFeature()
+        else:
+            self.layer.ResetReading()
+            nextFeature = self.layer.GetNextFeature()
+
+        ord = 0
+        while nextFeature is not None:
+            if self.id_column is not None:
+                id = nextFeature.GetField(self.id_column)
+                nextFeature = lay.GetNextFeature()
+            else:
+                id = nextFeature.GetFID()
+                nextFeature = self.layer.GetNextFeature()
+            self.ordinals[ord] = id
+            self.ids[id] = ord
+            ord = ord + 1
+        if self.id_column is not None:
+            self.datasource.ReleaseResultSet(lay)
+
+    def TableName(self):
+        """Return the name of the table, which is the name of the layer
+        """
+        return self.tablename
+
+    def Title(self):
+        """Return the title of the table.
+        """
+        return self.tablename
+
+    def Dependencies(self):
+        """Return an empty tuple.
+        """
+        return ()
+
+    def NumColumns(self):
+        """Return the number of columns.
+        """
+        return len(self.columns)
+
+    def Columns(self):
+        """Return all columns.
+        """
+        return self.columns
+
+    def Column(self, col):
+        """Return the column col. col can be either a string or an integer.
+        """
+        return self.column_map[col]
+
+    def HasColumn(self, col):
+        """Return if column col exists. col can be either a string or an
+        integer.
+        """
+        return self.column_map.has_key(col)
+
+    def NumRows(self):
+        """Return the number of rows in the table, which equals the number of
+        features in the layer.
+        """
+        return len(self.ids)
+
+    def RowIdToOrdinal(self, gid):
+        """Return the row ordinal given its id
+        """
+        if gid < 0:
+            return gid
+        else:
+            ord = self.ids[gid]
+            return ord
+
+    def RowOrdinalToId(self, num):
+        """Return the rowid for given its ordinal
+        """
+        if num >= 0:
+            id = self.ordinals[num]
+            return id
+        else:
+            return num
+
+    def ReadRowAsDict(self, row, row_is_ordinal = 0):
+        """Return a dictionary which contains all the fields.
+        """
+        if row_is_ordinal == 0:
+            rowId = self.RowIdToOrdinal(row)
+        else:
+            rowId = row
+        result = {}
+        for i in range(self.NumColumns()):
+            result[self.Column(i).name] = self.content[rowId][i]
+        return result
+
+    def ReadValue(self, row, col, row_is_ordinal = 0):
+        """Return the requested value.
+        """
+        if row_is_ordinal == 0:
+            rowId = self.RowIdToOrdinal(row)
+        else:
+            rowId = row
+        colIndex = self.column_map[col].index
+        return self.content[rowId][colIndex]
+
+    def ValueRange(self, col):
+        """Return the value range of the given column (given as string).
+        """
+
+        result = self.datasource.ExecuteSQL("SELECT min(%s), max(%s) FROM %s"
+                %(col, col, self.layer.GetName()))
+        result.ResetReading()
+        feature = result.GetNextFeature()
+        try:
+            min = feature.GetField(0)
+            max = feature.GetField(1)
+        except:
+            min = 0
+            max = 0
+        self.datasource.ReleaseResultSet(result)
+        return (min, max)
+
+    def UniqueValues(self, col):
+        """Return all the values being found in the column (given as string).
+        """
+        result = self.datasource.ExecuteSQL((
+                    "SELECT DISTINCT %s FROM %s ORDER BY %s"
+                     %(col,self.layer.GetName(),col)))
+        values = []
+        while 1:
+            feature = result.GetNextFeature()
+            if feature is None:
+                break
+            values.append(feature.GetField(0))
+        self.datasource.ReleaseResultSet(result)
+        return values
+
+    def SimpleQuery(self, left, comparison, right):
+        """Return the FIDs resulting from the given query.
+        """
+
+        if comparison not in ("==", "!=", "<", "<=", ">=", ">"):
+            raise ValueError("Comparison operator %r not allowed" %comparison)
+
+        if comparison == "==":
+            comparison = "="
+
+        if isinstance(right, OGRColumn):
+            right_template = right.name
+        else:
+            right_template = right
+
+        if self.id_column is None:
+            id = "FID"
+        else:
+            id = self.id_column
+        query = ("SELECT %s FROM %s WHERE %s %s %s ORDER BY %s"
+                % (id, self.tablename,left.name, comparison,
+                   right_template, id))
+
+        lay = self.datasource.ExecuteSQL(query)
+        result = []
+        while lay is not None:
+            feature = lay.GetNextFeature()
+            if feature is None:
+                break
+            result.append(feature.GetField(0))
+        if lay is not None:
+            self.datasource.ReleaseResultSet(lay)
+        return result
+
+    def Id_column(self):
+        """Return the id_column.
+        """
+        return self.id_column
+
+
+class OGRColumn:
+    """Column description for a table for an ogr file
+    """
+
+    def __init__(self, name, type, index):
+        self.name = name
+        self.type = type
+        self.index = index

Added: packages/thuban/branches/upstream/current/Extensions/ogr/ogrstart.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/ogr/ogrstart.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/ogr/ogrstart.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,238 @@
+# Copyright (c) 2004,2006 by Intevation GmbH    vim:encoding=latin-1:
+# Authors:
+# Nina Hüffmeyer <nhueffme at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2721 $"
+# $Source$
+# $Id: ogrstart.py 2721 2007-01-13 15:11:42Z dpinte $
+
+# Needed wx.-toolkit classes
+import wx
+
+# We need os.path
+import os
+
+# use _() already now for all strings that may later be translated
+from Thuban import _
+
+from Thuban.Model.layer import Layer
+
+# Import ogr related classes
+from Extensions.ogr import ogrshapes, ogrdialog
+from Extensions.ogr.ogrdialog import ChooseOGRDBTableDialog
+
+from Thuban.UI.menu import Menu
+from Thuban.UI.mainwindow import _has_dbconnections, _has_gdal_support
+
+def open_with_ogr(context):
+    '''Open a file supported by ogr.
+    '''
+    canvas = context.mainwindow.canvas
+    map = canvas.Map()
+
+    # Get the file to be opened
+    dlg = wx.FileDialog(canvas, _("Select a data file"),
+                           context.application.Path("data"), "",
+                           _("Shapefiles (*.shp)") + "|*.shp|" +
+                           _("GML files (*.gml)") + "|*.gml|" +
+                           _("MapInfo files (*.tab)") + "|*.tab|" +
+                           _("DGN files (*.dgn)") + "|*.dgn|" +
+                           _("CSV files (*.csv)") + "|*.csv|" +
+                           _("All Files (*.*)") + "|*.*|",
+                           wx.OPEN | wx.MULTIPLE)
+
+    if dlg.ShowModal() == wx.ID_OK:
+        filenames = dlg.GetPaths()
+        for filename in filenames:
+            title = os.path.splitext(os.path.basename(filename))[0]
+            has_layers = map.HasLayers()
+            layerDlg = ogrdialog.ChooseLayer(canvas, filename)
+            if layerDlg.ShowModal() == wx.ID_OK:
+                layername = layerDlg.GetLayer()
+                try:
+                    session = context.application.Session()
+                    store = OpenFileShapestore(context.mainwindow, session,
+                                               filename, layername)
+                    session.AddShapeStore(store)
+                except:
+                    # the layer couldn't be opened
+                    context.mainwindow.RunMessageBox(_("Add Layer"),
+                                _("Can't open the file '%s'.") % filename)
+                else:
+                    if store is not None:
+                        layer = Layer(title, store)
+                        map.AddLayer(layer)
+                        if not has_layers:
+                            # if we're adding a layer to an empty map, fit the
+                            # new map to the window
+                            canvas.FitMapToWindow()
+                    context.application.SetPath("data",filename)
+        dlg.Destroy()
+
+def select_file_format(context):
+    ''' Display all available supported formats.
+    '''
+
+    canvas = context.mainwindow.canvas
+    file = None
+    map = canvas.Map()
+
+    session = context.application.Session()
+
+    dlg = ogrdialog.ChooseFileFormat(canvas, session)
+
+    if dlg.ShowModal() == wx.ID_OK:
+        pass
+    dlg.Destroy()
+
+def open_db(context):
+    ''' Open a table in a database as a layer.
+    '''
+
+    canvas = context.mainwindow.canvas
+    map = canvas.Map()
+
+    session = context.application.Session()
+    dlg = ChooseOGRDBTableDialog(canvas, session)
+
+    if dlg.ShowModal() == wx.ID_OK:
+        dbconn, connString, dbtable, id_column = dlg.GetTable()
+        try:
+            store = OpenDBShapestore(session, dbconn, dbtable, id_column,
+                                            None)
+            session.AddShapeStore(store)
+
+            layer = Layer(dbtable, store)
+
+            has_layers = map.HasLayers()
+            map.AddLayer(layer)
+            if not has_layers:
+                canvas.FitMapToWindow()
+        except:
+            # Some error occured while initializing the layer
+            context.mainwindow.RunMessageBox(_("Add Layer from database"),
+                               _("Can't open the database table '%s'")
+                               % dbtable)
+    dlg.Destroy()
+
+def open_OGRConnection(context):
+    """Open a datasource with an OGRConnection string."""
+    canvas = context.mainwindow.canvas
+    map = canvas.Map()
+
+    session = context.application.Session()
+    dlg = ogrdialog.OGRConnectionDialog(canvas, session)
+
+    if dlg.ShowModal() == wx.ID_OK:
+        dsname = dlg.GetDatasourceName()
+
+        layerDlg = ogrdialog.ChooseLayer(canvas, dsname)
+        if layerDlg.ShowModal() == wx.ID_OK:
+            layername = layerDlg.GetLayer()
+            try:
+                store = ogrshapes.OGRShapeStore(session, dsname, layername)
+                session.AddShapeStore(store)
+            except:
+                # the layer couldn't be opened
+                context.mainwindow.RunMessageBox(("Add Layer"),
+                            ("Can't open the file '%s'.") % dsname)
+            else:
+                layer = Layer(dsname, store)
+                has_layers = map.HasLayers()
+                map.AddLayer(layer)
+                if not has_layers:
+                    # if we're adding a layer to an empty map, fit the
+                    # new map to the window
+                    canvas.FitMapToWindow()
+    dlg.Destroy()
+
+def OpenFileShapestore(mainwindow, session, filename, layername):
+    """Open a datasource and add the required layer.
+    """
+    try:
+        store = ogrshapes.OGRFileShapeStore(session, filename, layername)
+        return store
+    except:
+        # Some error occured while initializing the layer
+        mainwindow.RunMessageBox(_("Open datasource"),
+                           _("Can't open the datasource '%s'")
+                           % filename)
+        return None
+
+def OpenDBShapestore(session, dbconn, layername, id_column, geo_column):
+    """Open a datasource and add the required layer.
+
+    dbconn     - shold be a DBConnection
+    layername  - the name of the table which should opened as layer
+    id_column  - the column name which should be used as ID column
+    geo_column - always None for ogr
+    """
+    try:
+        filename = "PG: dbname=%s" %dbconn.dbname
+        if dbconn.host is not "":
+            filename = filename + " host=%s" % dbconn.host
+        if dbconn.user is not "":
+            filename = filename + " user=%s" % dbconn.user
+        if dbconn.password is not "":
+            filename = filename + " password=%s" % dbconn.password
+        if dbconn.port is not "":
+            filename = filename + " port=%s" % dbconn.port
+        store = ogrshapes.OGRShapeStore(session, filename, layername,
+                                        id_column = id_column)
+        return store
+    except:
+        # Some error occured while initializing the layer
+        context.mainwindow.RunMessageBox(_("Open datasource"),
+                           _("Can't open the datasource '%s'")
+                           % filename)
+
+# Thuban has named commands which can be registered in the central
+# instance registry.
+from Thuban.UI.command import registry, Command
+
+# The instance of the main menu of the Thuban application
+# See Thuban/UI/menu.py for the API of the Menu class
+from Thuban.UI.mainwindow import main_menu
+
+
+# find the map menu (create a new if not found)
+#map_menu = main_menu.FindOrInsertMenu('map', _('Map'))
+#ogr_menu = Menu("ogr", _("Open layer via OGR"),[])
+# as long as there we are not stable, better add to "Extentions" marked "beta"
+map_menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))
+ogr_menu = Menu("ogr", _("(testing) Open layer via OGR"),[])
+
+
+ogrsupport = ogrshapes.has_ogr_support()
+
+# create new commands and register them
+registry.Add(Command('open_ogr_files', 'Open an ogr-file', open_with_ogr,
+                     sensitive = _has_gdal_support,
+                     helptext = 'Open a file supported from ogr'))
+
+#registry.Add(Command('select_file_format', 'Select a file format',
+#                     select_file_format, 
+#                     helptext = "Select a file format supported from ogr"))
+
+registry.Add(Command('open_db', 'Open a layer from a database',
+                     open_db,
+                     sensitive = _has_dbconnections,
+                     helptext = "Open a layer from a database, e.g. PostGIS"))
+
+registry.Add(Command('open_OGRConnection',
+                     ("Open a datasource with an OGRConnection string"),
+                     open_OGRConnection,
+                     sensitive = _has_gdal_support, helptext = 
+                     "Open a datasource with an OGRConnection string"))
+
+# finally bind the new command with an entry in the extensions menu
+ogr_menu.InsertItem("open_ogr_files")
+#ogr_menu.InsertItem('select_file_format')
+ogr_menu.InsertItem('open_db')
+ogr_menu.InsertItem('open_OGRConnection')
+
+# Add ogr menu to map menu
+map_menu.InsertItem(ogr_menu, after = "rasterlayer_add")

Added: packages/thuban/branches/upstream/current/Extensions/ogr/test/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/ogr/test/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/ogr/test/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,7 @@
+# -*- coding: iso-8859-1 -*-    vim:encoding=latin-1:
+# Copyright (C) 2004 by Intevation GmbH
+# Authors:
+# Nina Hüffmeyer <nhueffme at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.

Added: packages/thuban/branches/upstream/current/Extensions/ogr/test/test_OGRShapestore.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/ogr/test/test_OGRShapestore.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/ogr/test/test_OGRShapestore.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,256 @@
+# Copyright (C) 2004,2006 by Intevation GmbH        vim:encoding=latin-1:
+# Authors:
+# Nina Hüffmeyer <nhueffme at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+__version__ = "$Revision: 2713 $"
+# $Source$
+# $Id: test_OGRShapestore.py 2713 2006-10-26 16:37:42Z bernhard $
+
+"""Tests for ogrshapes"""
+
+import os
+import sys
+import unittest
+
+try:
+    import ogr
+    ogr_imported = True
+except ImportError:
+    # No ogr available. The tests will
+    # be skipped completely.
+    ogr_imported = False
+
+# If run directly as a script, add Thuban's test directory to the path
+# as well as the extensions own directory (i.e. parent).
+# Otherwise we assume that the importing code has already done it.
+if __name__ == "__main__":
+    sys.path.append(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])),
+                                 "..", "..", "test"))
+    sys.path.append(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])),
+                                 ".."))
+
+import support
+support.initthuban()
+
+from Extensions.ogr.ogrshapes import OGRShapeStore, OGRShape, \
+     SHAPETYPE_POINT, SHAPETYPE_ARC, SHAPETYPE_POLYGON
+from Thuban.Model.data import RAW_PYTHON
+from Thuban.Model.table import FIELDTYPE_INT
+from Thuban.Model.session import Session
+
+
+def skip_if_no_ogr():
+    if not ogr_imported:
+        raise support.SkipTest( \
+            "Can't run ogr tests because ogr couldn't be imported.")
+
+class TestOGRShapeStore_shp(unittest.TestCase, support.FloatComparisonMixin):
+
+    def setUp(self):
+        """Initialize self.session and open shapefile, if ogr could be
+        imported.
+        """
+        skip_if_no_ogr()
+        self.session = Session("TestSession")
+        self.filename_arc = os.path.join("..", "Data", "iceland",
+                                        "roads-line.shp")
+        self.store_arc = OGRShapeStore(self.session, self.filename_arc,
+                                        "roads-line")
+
+        self.filename_point = os.path.join("..", "Data", "iceland",
+                                        "cultural_landmark-point.shp")
+        self.store_point = OGRShapeStore(self.session, self.filename_point,
+                                        "cultural_landmark-point")
+
+        self.filename_poly = os.path.join("..", "Data", "iceland",
+                                        "political.shp")
+        self.store_poly = OGRShapeStore(self.session, self.filename_poly,
+                                        "political")
+
+    def tearDown(self):
+        """Call self.session.Destroy() and reset self.session to None"""
+        self.session = None
+        self.store_arc = None
+        self.store_point = None
+        self.store_poly = None
+
+    def test_shape_type(self):
+        """Test OGRShapeStore.ShapeType() with arc shapes"""
+        self.assertEquals(self.store_arc.ShapeType(), SHAPETYPE_ARC)
+        self.assertEquals(self.store_point.ShapeType(), SHAPETYPE_POINT)
+        self.assertEquals(self.store_poly.ShapeType(), SHAPETYPE_POLYGON)
+
+    def test_raw_format(self):
+        """Test OGRShapeStore.RawShapeFormat() with ogr file"""
+        self.assertEquals(self.store_arc.RawShapeFormat(), RAW_PYTHON)
+        self.assertEquals(self.store_point.RawShapeFormat(), RAW_PYTHON)
+        self.assertEquals(self.store_poly.RawShapeFormat(), RAW_PYTHON)
+
+    def test_boundingbox(self):
+        """Test OGRShapeStore.BoundingBox() with arc shapes"""
+        self.assertFloatSeqEqual(self.store_arc.BoundingBox(),
+                                [-24.450359344482422, 63.426830291748047,
+                                -13.55668830871582, 66.520111083984375])
+        self.assertFloatSeqEqual(self.store_point.BoundingBox(),
+                                [-23.806047439575195, 63.405960083007812,
+                                -15.12291431427002, 66.36572265625])
+        self.assertFloatSeqEqual(self.store_poly.BoundingBox(),
+                                [-24.546524047851562, 63.286754608154297,
+                                -13.495815277099609, 66.563774108886719])
+
+    def test_num_shapes(self):
+        """Test OGRShapeStore.NumShapes() with arc shapes"""
+        self.assertEquals(self.store_arc.NumShapes(), 839)
+        self.assertEquals(self.store_point.NumShapes(), 34)
+        self.assertEquals(self.store_poly.NumShapes(), 156)
+
+    def test_shapes_in_region(self):
+        """Test OGRShapeStore.ShapesInRegion() with arc shapes"""
+        shapes_arc = self.store_arc.ShapesInRegion((-22.78, 63.96, 
+                                                    -22.72, 64.0))
+        self.assertEquals([s.ShapeID() for s in shapes_arc], [769, 771])
+
+        shapes_point = self.store_point.ShapesInRegion((-23.0, 63.0, 
+                                                        -22.0, 64.0))
+        self.assertEquals([s.ShapeID() for s in shapes_point], [29, 31])
+
+        shapes_poly = self.store_poly.ShapesInRegion((-23.0, 63.0, -22.0, 64.0))
+        self.assertEquals([s.ShapeID() for s in shapes_poly], [144])
+
+    def test_all_shapes(self):
+        """Test OGRShapeStore.AllShapes()"""
+        self.assertEquals([s.ShapeID() for s in self.store_arc.AllShapes()],
+                            range(self.store_arc.NumShapes()))
+        self.assertEquals([s.ShapeID() for s in self.store_point.AllShapes()],
+                            range(self.store_point.NumShapes()))
+        self.assertEquals([s.ShapeID() for s in self.store_poly.AllShapes()],
+                            range(self.store_poly.NumShapes()))
+
+    def test_shape_Points(self):
+        """Test OGRShapeStore.Shape() with arc shapes"""
+        self.assertPointListEquals(self.store_arc.Shape(32).Points(),
+                                [[(-15.08217430114746, 66.2773818969726),
+                                (-15.02635002136230, 66.2733917236328)]])
+        self.assertPointListEquals(self.store_point.Shape(13).Points(),
+                                [[(-15.364621162414551, 65.6103515625)]])
+        self.assertPointListEquals(self.store_poly.Shape(20).Points(),
+                                [[(-22.233562469482422, 64.4395751953125),
+                                (-22.244234085083008, 64.441192626953125),
+                                (-22.233894348144531, 64.446701049804688),
+                                (-22.226711273193359, 64.44439697265625),
+                                (-22.23356246948242, 64.4395751953125)]])
+
+    def test_shape_shapeid(self):
+        """Test OGRShapeStore.Shape(i).ShapeID()"""
+        self.assertEquals(self.store_arc.Shape(5).ShapeID(), 5)
+        self.assertEquals(self.store_point.Shape(13).ShapeID(), 13)
+        self.assertEquals(self.store_point.Shape(20).ShapeID(), 20)
+
+    def test_shape_compute_bbox(self):
+        """Test bbox of one shape"""
+        self.assertFloatSeqEqual(self.store_arc.Shape(32).compute_bbox(),
+                                (-15.08217430114746, 66.2733917236328,
+                                -15.02635002136230, 66.2773818969726))
+        self.assertFloatSeqEqual(self.store_point.Shape(13).compute_bbox(),
+                                (-15.364621162414551, 65.6103515625,
+                                -15.364621162414551, 65.6103515625))
+        self.assertFloatSeqEqual(self.store_poly.Shape(20).compute_bbox(),
+                                (-22.244234085083008, 64.4395751953125,
+                                -22.226711273193359, 64.446701049804688))
+
+
+class TestOGRTable(unittest.TestCase, support.FloatComparisonMixin):
+
+    def setUp(self):
+        """Initialize"""
+        skip_if_no_ogr()
+        self.session = Session("TestSession")
+        self.filename = os.path.join("..","Data", "iceland","roads-line.shp")
+        self.store_arc = OGRShapeStore(self.session, self.filename,
+                                        "roads-line")
+        self.table = self.store_arc.Table()
+
+    def tearDown(self):
+        """Call self.session.Destroy() and reset self.session to None"""
+        self.session = None
+        self.store_arc = None
+        self.table = None
+
+    def test_Dependencies(self):
+        """Test dependencies, which is always ()"""
+        self.assertEquals(self.table.Dependencies(), ())
+
+    def test_NumColumns(self):
+        """Test number of columns"""
+        self.assertEquals(self.table.NumColumns(), 9)
+
+    def test_Columns(self):
+        """Test columns, which are instances of OGRColumn"""
+        self.assertEquals(len(self.table.Columns()), 9)
+        self.assertEquals(self.table.Columns()[0].name, "FNODE_")
+        self.assertEquals(self.table.Columns()[0].type, FIELDTYPE_INT)
+        self.assertEquals(self.table.Columns()[0].index, 0)
+
+    def test_Column(self):
+        """Test column, which is instance of OGRColumn"""
+        self.assertEquals(self.table.Column(0).name, "FNODE_")
+        self.assertEquals(self.table.Column(0).type, FIELDTYPE_INT)
+        self.assertEquals(self.table.Column(0).index, 0)
+        self.assertEquals(self.table.Column("FNODE_").type, FIELDTYPE_INT)
+        self.assertEquals(self.table.Column("FNODE_").index, 0)
+
+    def test_HasColumn(self):
+        """Test HasColumn(), which can be called either with an integer or 
+        a string"""
+        self.assert_(self.table.HasColumn(0))
+        self.assert_(self.table.HasColumn("FNODE_"))
+
+    def test_NumRows(self):
+        """Test number of rows, which equals the number of features"""
+        self.assertEquals(self.table.NumRows(), 839)
+
+    def test_RowIdToOrdinal(self):
+        self.assertEqual(self.table.RowIdToOrdinal(5),5)
+
+    def test_RowOrdinalToId(self):
+        self.assertEqual(self.table.RowOrdinalToId(5),5)
+
+    def test_ReadRowAsDict(self):
+        """Test ReadRowAsDict()"""
+        self.assertEquals(len(self.table.ReadRowAsDict(0)), 9)
+        self.assertEquals(self.table.ReadRowAsDict(0, row_is_ordinal = 1),
+                        {"FNODE_": 3,
+                        "TNODE_": 1,
+                        "LPOLY_": 146,
+                        "RPOLY_": 146,
+                        "LENGTH": 0.156,
+                        "RDLINE_": 1,
+                        "RDLINE_ID": 879,
+                        "RDLNTYPE": 3,
+                        "RDLNSTAT": 1})
+
+    def test_ReadValue(self):
+        """Test ReadValue()"""
+        self.assertEquals(self.table.ReadValue(0,0,0), 3)
+        self.assertEquals(self.table.ReadValue(0,"FNODE_",0),3)
+
+    def test_ValueRange(self):
+        """Test ValueRange()"""
+        self.assertEquals(self.table.ValueRange("FNODE_"), (1, 733))
+
+    def test_UniqueValues(self):
+        """Test UniqueValues()"""
+        self.assertFloatSeqEqual(self.table.UniqueValues("RDLNTYPE"), [2,3,8])
+
+    def test_SimpleQuery(self):
+        """Test SimpleQuery()"""
+        self.assertEquals(self.table.SimpleQuery(self.table.Column("LENGTH"),
+                        "==", 0.156),[0, 24, 317])
+
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/Extensions/ogr/x.diff
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/ogr/x.diff	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/ogr/x.diff	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,103 @@
+Index: test/__init__.py
+===================================================================
+--- test/__init__.py	(Revision 2711)
++++ test/__init__.py	(Arbeitskopie)
+@@ -1,4 +1,4 @@
+-# -*- coding: iso-8859-1 -*-
++# -*- coding: iso-8859-1 -*-    vim:encoding=latin-1:
+ # Copyright (C) 2004 by Intevation GmbH
+ # Authors:
+ # Nina Hüffmeyer <nhueffme at intevation.de>
+Index: test/test_OGRShapestore.py
+===================================================================
+--- test/test_OGRShapestore.py	(Revision 2711)
++++ test/test_OGRShapestore.py	(Arbeitskopie)
+@@ -1,6 +1,6 @@
+-# Copyright (C) 2004,2006 by Intevation GmbH
++# Copyright (C) 2004,2006 by Intevation GmbH        vim:encoding=latin-1:
+ # Authors:
+-# Nina Hueffmeyer <nhueffme at intevation.de>
++# Nina Hüffmeyer <nhueffme at intevation.de>
+ #
+ # This program is free software under the GPL (>=v2)
+ # Read the file COPYING coming with the software for details.
+Index: ogrshapes.py
+===================================================================
+--- ogrshapes.py	(Revision 2711)
++++ ogrshapes.py	(Arbeitskopie)
+@@ -1,6 +1,6 @@
+-# Copyright (C) 2004 by Intevation GmbH
++# Copyright (C) 2004 by Intevation GmbH     vim:encoding=latin-1:
+ # Authors:
+-# Nina Hueffmeyer <nhueffme at intevation.de>
++# Nina Hüffmeyer <nhueffme at intevation.de>
+ #
+ # This program is free software under the GPL (>=v2)
+ # Read the file COPYING coming with the software for details.
+Index: __init__.py
+===================================================================
+--- __init__.py	(Revision 2711)
++++ __init__.py	(Arbeitskopie)
+@@ -1,6 +1,6 @@
+-# Copyright (C) 2004 by Intevation GmbH
++# Copyright (C) 2004 by Intevation GmbH     vim:encoding=latin-1:
+ # Authors:
+-# Nina Hueffmeyer <nhueffme at intevation.de>
++# Nina Hüffmeyer <nhueffme at intevation.de>
+ #
+ # This program is free software under the GPL (>=v2)
+ # Read the file COPYING coming with the software for details.
+@@ -25,12 +25,12 @@
+          # in the global test routine.
+ 
+ # perform the registration of the extension
+-from Thuban import _
++from Thuban import _, internal_from_unicode
+ from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+ 
+ ext_registry.add(ExtensionDesc(
+     name = 'OGRstart',
+     version = '0.9.0',
+-    authors= [ 'Nina Hueffmeyer' ],
++    authors= [ internal_from_unicode(u'Nina H\xfcffmeyer') ],
+     copyright = '2004 Intevation GmbH',
+     desc = _("Open a file supported by ogr.")))
+Index: ogrstart.py
+===================================================================
+--- ogrstart.py	(Revision 2711)
++++ ogrstart.py	(Arbeitskopie)
+@@ -1,4 +1,4 @@
+-# Copyright (c) 2004 by Intevation GmbH
++# Copyright (c) 2004,2006 by Intevation GmbH    vim:encoding=latin-1:
+ # Authors:
+ # Nina Hüffmeyer <nhueffme at intevation.de>
+ #
+@@ -199,9 +199,13 @@
+ 
+ 
+ # find the map menu (create a new if not found)
+-map_menu = main_menu.FindOrInsertMenu('map', _('Map'))
+-ogr_menu = Menu("ogr", _("Open layer via OGR"),[])
++#map_menu = main_menu.FindOrInsertMenu('map', _('Map'))
++#ogr_menu = Menu("ogr", _("Open layer via OGR"),[])
++# as long as there we are not stable, better add to "Extentions" marked "beta"
++map_menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))
++ogr_menu = Menu("ogr", _("(testing) Open layer via OGR"),[])
+ 
++
+ ogrsupport = ogrshapes.has_ogr_support()
+ 
+ # create new commands and register them
+Index: ogrdialog.py
+===================================================================
+--- ogrdialog.py	(Revision 2711)
++++ ogrdialog.py	(Arbeitskopie)
+@@ -1,6 +1,6 @@
+-# Copyright (c) 2001, 2003, 2004 by Intevation GmbH
++# Copyright (c) 2001, 2003, 2004 by Intevation GmbH     vim:encoding=latin-1:
+ # Authors:
+-# Martin Mueller <mmueller at intevation.de>
++# Martin Müller <mmueller at intevation.de>
+ # Bernhard Herzog <bh at intevation.de>
+ #
+ # This program is free software under the GPL (>=v2)

Added: packages/thuban/branches/upstream/current/Extensions/profiling/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/profiling/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/profiling/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,22 @@
+# Copyright (c) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+# import the actual module
+import profiling
+
+# perform the registration of the extension
+from Thuban import _
+from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+
+ext_registry.add(ExtensionDesc(
+    name = 'profiling',
+    version = '1.0.0',
+    authors= [ 'Bernhard Herzog' ],
+    copyright = '2003, 2004 Intevation GmbH',
+    desc = _("Provide a profiler and a timer\n"
+             "for screen rendering.")))
+

Added: packages/thuban/branches/upstream/current/Extensions/profiling/profiling.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/profiling/profiling.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/profiling/profiling.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,148 @@
+# Copyright (C) 2003, 2004 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de> (2003)
+# Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Performance Measurement
+
+This module implements two Thuban commands in a new Profiling menu:
+
+   Profile Screen Render -- Run the screen rendering code in a profile
+
+   Time Screen Render -- Measure the time taken for a complete redraw
+
+See the individual functions for more details.
+"""
+
+__version__ = "$Revision: 2721 $"
+# $Source$
+# $Id: profiling.py 2721 2007-01-13 15:11:42Z dpinte $
+
+import os
+import StringIO
+import sys
+import tempfile
+import profile
+import time
+import pstats
+
+from wx.lib.dialogs import ScrolledMessageDialog
+
+from Thuban import _
+from Thuban.UI.command import registry, Command
+from Thuban.UI.mainwindow import main_menu
+
+#
+# Customization
+#
+# Assign to these in your ~/.thuban/thubanstart
+
+# The machine specific profiler bias. See the standard python profile
+# module for details on how to find out which value to use.
+profiler_bias = 0
+
+# The directory the profile output is to be written to
+# (Call mktemp once to initialize tempfile.tempdir)
+tempfile.mktemp()
+profile_dir = tempfile.tempdir
+
+# Wether to pop up a dialog box with the result.
+popup_dialog_box = True
+
+
+#
+#       Timing and profiling a complete redraw
+#
+
+def do_redraw(context):
+    """Perform a complete redraw in the canvas in context"""
+    canvas = context.mainwindow.canvas
+
+    # Make sure there are no no finished bitmaps and active renderer
+    canvas.full_redraw()
+
+    # Iterate until all is drawn
+    for c in canvas._render_iterator():
+        pass
+
+
+#
+# Profiling the redraw
+#
+
+
+def profile_screen_renderer(context):
+    """Script to run the redraw in the profiler
+
+    The data gathered by the profiler will be written to
+    <TMPDIR>/thuban-render.profile (<TMPDIR> is your system specific
+    temporary directory.
+
+    See the python documentation of the profile and pstats modules for
+    how to access the data in the generated .profile file.
+    """
+    print "profiling screen renderer...",
+    sys.stdout.flush()
+    prof = profile.Profile(bias = profiler_bias)
+    prof.runctx("do_redraw(context)", globals(), locals())
+    filename = os.path.join(profile_dir, "thuban-render.profile")
+    prof.dump_stats(filename)
+    print "done and saved to", filename
+
+    if popup_dialog_box:
+        # catch the printout to stdout so that we can present the
+        # text in a dialog
+        f = StringIO.StringIO()
+        orig_stdout = sys.stdout
+        sys.stdout = f
+        try:
+            p = pstats.Stats(filename)
+            msg = _('These are the statistics sorted by cumulative time:')
+            p.strip_dirs().sort_stats('cumulative').print_stats()
+            m = f.getvalue()
+            msg = '%s\n\n%s' % (msg, m)
+        finally:
+            sys.stdout = orig_stdout
+
+        dlg = ScrolledMessageDialog(context.mainwindow, msg,
+                                      _('Profile Screen Render'))
+        dlg.ShowModal()
+
+
+registry.Add(Command("profile_screen_renderer", _('Profile Screen Render'),
+                     profile_screen_renderer,
+                     helptext = _('Profile the screen render')))
+
+
+#
+# Timing the redraw
+#
+
+def time_screen_renderer(context):
+    """Script to measure the time of a complete redraw.
+
+    The time taken will be printed to stdout.
+    """
+    start = time.clock()
+    do_redraw(context)
+    duration = time.clock() - start
+    msg = _('Redraw finished in %g seconds.') % duration
+    if popup_dialog_box:
+        context.mainwindow.RunMessageBox(_('Time Screen Render'), msg)
+    else:
+        print msg
+
+
+registry.Add(Command("time_screen_renderer", _('Time Screen Render'),
+                     time_screen_renderer,
+                     helptext = _('Time the screen render')))
+
+# find the extensions menu (create it anew if not found)
+extensions_menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))
+
+profiler_menu = extensions_menu.InsertMenu("profiler", _('&Profiler'))
+profiler_menu.InsertItem("time_screen_renderer")
+profiler_menu.InsertItem("profile_screen_renderer")

Added: packages/thuban/branches/upstream/current/Extensions/svgexport/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/svgexport/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/svgexport/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,33 @@
+# Copyright (C) 2004, 2005, 2006, 20007 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de> (2004)
+# Jan-Oliver Wagner <jan at intevation.de> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+# import the actual modules
+from os import environ
+from sys import platform
+try:
+    if platform != 'win32':
+      dummy = environ["DISPLAY"]
+    import svgsaver
+    import maplegend
+except:    
+    pass # For non-win32 platform, we don't have a DISPLAY, so don't import 
+         # the modules (for test mode)
+         # For win32 platform, there is  always have a graphical mode
+         # Not sure whether this is the best method to avoid problems
+         # in the global test routine.
+
+# perform the registration of the extension
+from Thuban import _
+from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+
+ext_registry.add(ExtensionDesc(
+    name = 'SVG Export',
+    version = '1.0.1',
+    authors= [ 'Markus Rechtien', 'Bernhard Reiter' ],
+    copyright = '2004-2007 Intevation GmbH',
+    desc = _("Export the current map and legend in Thuban-map-SVG format.")))

Added: packages/thuban/branches/upstream/current/Extensions/svgexport/maplegend.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/svgexport/maplegend.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/svgexport/maplegend.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,178 @@
+# Copyright (c) 2001, 2002, 2003 by Intevation GmbH
+# Authors:
+#     Markus Rechtien <markus at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2721 $"
+# $Source$
+# $Id: maplegend.py 2721 2007-01-13 15:11:42Z dpinte $
+
+
+"""
+Write a basic map legend in svg format.
+"""
+
+
+# Needed wx.-toolkit classes
+import wx
+
+# We need os.path
+import os
+
+# Use _() already now for all strings that may later be translated
+from Thuban import _
+
+# Color related classes defined in the thuban model
+from Thuban.Model.color import Transparent, Color, Black
+
+# Different shape types
+from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
+    SHAPETYPE_POINT, RAW_SHAPEFILE
+
+# Import SVG related classes
+from svgmapwriter import SVGRenderer, VirtualDC, TRANSPARENT_PEN, \
+        TRANSPARENT_BRUSH, SOLID, Pen, Brush, Point
+
+
+BLACK_PEN = Pen()
+
+class SVGMapLegend(SVGRenderer):
+    """Class to render a basic map legend.
+    
+    """
+    def __init__(self, dc, map=None, scale=(1.0), offset=(0,0), 
+            region=(0,0,0,0), resolution = 72.0, 
+            honor_visibility = 1, destination_region = (0,0,0,0)):
+        SVGRenderer.__init__(self, dc, map, scale, offset, region,
+                resolution, honor_visibility)
+        self.destination_region = destination_region
+        self.factor = 1.0
+    
+    def RenderLegend(self, layers):
+        """Render the legend on the Map."""
+        dc = self.dc
+        dc.SetPen(BLACK_PEN)
+        dc.SetBrush(TRANSPARENT_BRUSH)
+        # Dimension stuff
+        width, height = dc.GetSizeTuple()
+        mminx, mminy, mmaxx, mmaxy = self.destination_region
+        textwidth, textheight = dc.GetTextExtent("0")
+        iconwidth  = iconheight = textheight
+        stepy = 12
+        dx = 12
+        posx = mmaxx + 20 + 10  # 20 pix distance mapframe/legend frame,
+                                # 10 pix inside legend frame
+        posy = mminy + 20       # 20 pix inside legend frame
+        #
+        self.dc.BeginGroup(meta={'Object':'legend', })
+        # Render the legend
+        dc.SetTextForeground(Black)
+        if layers:
+            layers.reverse()
+            for l in layers:
+                if l.Visible():
+                    # Render title
+                    dc.DrawText(l.Title(), posx, posy)
+                    posy+=stepy
+                    if l.HasClassification():
+                        # Render classification
+                        clazz = l.GetClassification()
+                        shapeType = l.ShapeType()
+                        for g in clazz:
+                            if g.IsVisible():
+                                self.Draw(dc, wx.Rect(posx+dx, 
+                                        posy-iconheight+2,
+                                        iconwidth, iconheight),
+                                        g.GetProperties(), shapeType)
+                                dc.DrawText(g.GetDisplayText(),
+                                        posx+2*dx+iconwidth, posy)
+                                posy+=stepy
+                    posy+=10
+        self.dc.EndGroup()
+
+    def Draw(self, dc, rect, prop, shapeType):
+        '''Draw little icon for a shape depending on given properties.'''
+        x = rect.GetX()
+        y = rect.GetY()
+        w = rect.GetWidth()
+        h = rect.GetHeight()
+
+        pen, brush = self.tools_for_property(prop)
+        dc.SetPen(pen)
+        dc.SetBrush(brush)
+
+        if shapeType == SHAPETYPE_ARC:
+            dc.DrawSpline([Point(x, y + h),
+                           Point(x + w/2, y + h/4),
+                           Point(x + w/2, y + h/4*3),
+                           Point(x + w, y)])
+
+        elif shapeType == SHAPETYPE_POINT:
+            dc.DrawCircle(x + w/2, y + h/2,
+                          (min(w, h) - prop.GetLineWidth())/2)
+                          
+        elif shapeType == SHAPETYPE_POLYGON:
+            dc.DrawRectangle(x, y, w, h)
+
+
+def write_legend(context):
+    """Export the data depending on the set properties.
+
+    This is the main export function.
+    """
+    canvas = context.mainwindow.canvas
+    file = None
+    map = canvas.Map()
+    #
+    if hasattr(canvas, "export_path"):
+        export_path = canvas.export_path
+    else:
+        export_path="."
+    # Get the file the session shall be written to
+    dlg = wx.FileDialog(canvas, _("Write SVG"), export_path, "", 
+            "Scalable Vector Graphics (*.svg)|*.svg", 
+            wx.SAVE|wx.OVERWRITE_PROMPT)
+    #
+    response = dlg.ShowModal()
+    if response == wx.ID_OK:
+        file = dlg.GetPath()
+    else: # Do nothing if choice was interrupted.
+        return 0
+        
+    # If the user selected a file
+    if file and map is not None:
+        canvas.export_path = os.path.dirname(file)
+        width, height = canvas.GetSizeTuple()
+        llx, lly = canvas.win_to_proj(0, height)
+        urx, ury = canvas.win_to_proj(width, 0)
+        mapwidth, mapheight = ((urx - llx), (ury - lly))
+        # 
+        selected_layer = map.Layers()
+        dc = VirtualDC(file, (mapwidth, mapheight, ))
+        dc.BeginExport()
+        #
+        renderer = SVGMapLegend(dc)
+        renderer.RenderLegend(selected_layer)
+        #
+        dc.EndExport()
+
+    
+# Thuban has named commands which can be registered in the central
+# instance registry.
+from Thuban.UI.command import registry, Command
+
+# The instance of the main menu of the Thuban application
+# See Thuban/UI/menu.py for the API of the Menu class
+from Thuban.UI.mainwindow import main_menu
+
+# create a new command and register it
+registry.Add(Command('write_legend', _('Write SVG Legend'), write_legend,
+                     helptext = _('Write a basic Legend for the map.')))
+
+# find the menu we want to be in (create it anew if not found)
+menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))
+
+# finally bind the new command with an entry in the extensions menu
+menu.InsertItem('write_legend')

Added: packages/thuban/branches/upstream/current/Extensions/svgexport/svgmapwriter.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/svgexport/svgmapwriter.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/svgexport/svgmapwriter.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,784 @@
+# Copyright (c) 2001, 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+#     Markus Rechtien <markus at intevation.de>
+#     Bernhard Reiter <bernhard at intevation.de> (2004, 2005)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+
+"""
+Classes needed to write a session in SVG format.
+"""
+
+# For compatibility with python 2.2
+from __future__ import generators
+
+
+__version__ = "$Revision: 2732 $"
+# $Source$
+# $Id: svgmapwriter.py 2732 2007-02-26 23:02:25Z bernhard $
+
+import sys
+
+# Verboseness level for debugging. Useful values: 0,1,2,3
+verbose=0
+log=sys.stdout.write
+
+# Regular expressions used with Fontnames
+import re
+# Combining strings
+from string import join
+# We need to determine some object types
+from types import ListType
+# for SetBaseID
+import binascii 
+
+from Thuban import _
+from Thuban.Model.data import SHAPETYPE_POINT, SHAPETYPE_ARC
+# VirtualDC extends XMLWriter
+from Thuban.Model.xmlwriter import XMLWriter, escape
+# Color related classes from the model of thuban
+from Thuban.Model.color import Transparent, Black
+# The SVGRenderer is subclass of BaseRenderer
+from Thuban.UI.baserenderer import BaseRenderer
+
+# Basic font map.
+fontMap = { "Times"     : re.compile("Times-Roman.*"),
+            "Helvetica" : re.compile("Helvetica.*"),
+            "Courier"   : re.compile("Courier.*"),
+            }
+
+# Possible values for svg line joins.
+svg_joins = {'miter':'miter', 'round':'round', 'bevel':'bevel'}
+# Possible values for svg line caps.
+svg_caps = {'':'', 'butt':'butt', 'round':'round', 'square':'square'}
+
+#
+# Some pseudo classes to be compatible with the Baserenderer-class.
+#
+class Point:
+    """Simple Point class to save x,y coordinates."""
+    def __init__(self, xp=0, yp=0):
+        self.x = xp
+        self.y = yp
+
+    def __repr__(self):
+        return "Point(%s, %s)" % (str(self.x), str(self.y))
+
+class Trafo:
+    """Class for transformation properties transfer."""
+    def __init__(self):
+        self.trafos = []
+    
+    def Append(self, type, coeffs):
+        """Append a transformation to the list."""
+        self.trafos.append((type, coeffs))
+    
+    def Count(self):
+        """Get the number of transformations in list."""
+        return len(self.trafos)
+    
+    def Pop(self):
+        """Pop and return a transformation from the end of the list."""
+        if len(self.trafos) > 0:
+            return self.trafos.pop()
+        else: return None
+
+class Pattern:
+    def __init__(self, solid=1):
+        self.solid = solid
+
+class Pen:
+    """Pen object for property transfer."""
+    def __init__(self, pcolor = Black, pwidth = 1, pdashes = None):
+        self.color = pcolor
+        self.width = pwidth
+        self.dashes = pdashes
+        self.join = 'round' 
+        self.cap = 'round'
+
+    def __str__(self):
+        return "Pen(%s,%s,%s,%s,%s)" % \
+            (str(self.color), str(self.width), str(self.dashes), 
+             str(self.join), str(self.cap))
+    
+    def GetColor(self):
+        return self.color
+
+    def GetWidth(self):
+        return self.width
+
+    def GetJoin(self):
+        return self.join
+    
+    def GetCap(self):
+        return self.cap
+    
+    def GetDashes(self):
+        if self.dashes is None or self.dashes is SOLID:
+            return []
+        else: return self.dashes
+
+class Brush:
+    """Brush property class."""
+    def __init__(self, bfill=Black, bpattern=None):
+        """Init the brush with the given values."""
+        self.fill = bfill
+        self.pattern = bpattern
+
+    def __str__(self):
+        return "Brush(" + str(self.fill) + ", " + str(self.pattern) + ")"
+
+    def GetColor(self):
+        return self.fill
+
+    def GetPattern(self):
+        return self.pattern
+
+class Font:
+    """Font class that accts as property object."""
+    def __init__(self, ffamily='Helvetica', fsize=12):
+        """Init the font with the given values."""
+        self.family = ffamily
+        self.size = fsize
+    
+    def GetFaceName(self):
+        """Return the fontfamily the font belongs to."""
+        return self.family
+    
+    def GetPointSize(self):
+        """Return the size of the font in points."""
+        return self.size
+
+# Instantiate an empty pen.
+TRANSPARENT_PEN = Pen(None, 0, None)
+# Instantiate an empty brush.
+TRANSPARENT_BRUSH = Brush(None, None)
+# Instantiate a solid pattern.
+SOLID = Pattern()
+
+class SVGMapWriterError(Exception):
+    """Get raised for problems when writing map-svg files.
+    
+    Occasion when this exception is raised:
+        Two layers have the same name to be used as BaseId: Name Clash 
+    """
+
+
+class SVGRenderer(BaseRenderer):
+    """Class to render a map onto a VirtualDC.
+    
+    This class, derived from BaseRenderer, will render a hole
+    session onto the VirtualDC to write all shapes as SVG code
+    to a file.
+    In opposite to other renderers it includes metadata, such as
+    shape ids and classification, when rendering the shapes.
+    """
+    def __init__(self, dc, map, scale, offset, region,
+                 resolution = 1.0, honor_visibility = 1):
+        """Init SVGRenderer and call superclass init."""
+        BaseRenderer.__init__(self, dc, map, scale, offset, region,
+                resolution, honor_visibility)
+        #
+        self.factor = (abs(region[2]) + abs(region[3])) / (2.0 * 1000.0)
+        self.used_baseids=[]   # needed for name clash check
+
+    def make_point(self, x, y):
+        """Return a Point object from two values."""
+        return Point(x, y)
+    
+    def label_font(self):
+        """Return the font object for the label layer.
+        
+        As we scale stuff, the fontsize also needs to be scaled."""
+        if verbose>1:
+            log("label_font() called.\n")
+        return Font(fsize=12*self.factor)
+
+    def tools_for_property(self, prop):
+        """Return a pen/brush tuple build from a property object."""
+        fill = prop.GetFill()
+        if fill is Transparent:
+            brush = TRANSPARENT_BRUSH
+        else:
+            brush = Brush(fill, SOLID)
+
+        stroke = prop.GetLineColor()
+        if stroke is Transparent:
+            pen = TRANSPARENT_PEN
+        else:
+            pen = Pen(stroke, prop.GetLineWidth() * self.factor, SOLID)
+        return pen, brush
+
+    def draw_polygon_shape(self, layer, points, pen, brush):
+        """Draw a polygon shape from layer with the given brush and pen
+
+        The shape is given by points argument which is a the return
+        value of the shape's Points() method. The coordinates in the
+        DC's coordinate system are determined with
+        self.projected_points.
+        """
+        points = self.projected_points(layer, points)
+
+        if verbose > 1:
+            log("drawing polygon with brush %s and pen %s\n" % 
+                (str(brush), str(pen)) )
+            if verbose > 2:
+                log("points: %s\n" %(repr(points)))
+
+        self.dc.SetBrush(brush)
+        self.dc.SetPen(pen)
+        self.dc.DrawPolygonPath(points)
+
+    def draw_point_shape(self, layer, points, pen, brush, size=2):
+        """Draw a point shape from layer with the given brush and pen
+
+        The shape is given by points argument which is a the return
+        value of the shape's Points() method. The coordinates in the
+        DC's coordinate system are determined with
+        self.projected_points.
+
+        The point is drawn as a circle centered on the point.
+        """
+        points = self.projected_points(layer, points)
+        if not points:
+            return
+
+        radius = self.factor * size
+        self.dc.SetBrush(brush)
+        self.dc.SetPen(pen)
+        for part in points:
+            for p in part:
+                self.dc.DrawCircle(p.x - radius, p.y - radius,
+                                    2.0 * radius)
+    
+    def draw_shape_layer_incrementally(self, layer):
+        """Draw a shapelayer incrementally.
+        """
+        dc = self.dc
+        brush = TRANSPARENT_BRUSH
+        pen   = TRANSPARENT_PEN
+
+        value = None
+        field = None
+        lc = layer.GetClassification()
+        field = layer.GetClassificationColumn()
+        defaultGroup = lc.GetDefaultGroup()
+        table = layer.ShapeStore().Table()
+
+        if lc.GetNumGroups() == 0:
+            # There's only the default group, so we can pretend that
+            # there is no field to classifiy on which makes things
+            # faster since we don't need the attribute information at
+            # all.
+            field = None
+            if verbose > 0: 
+                log("layer %s has no classification\n" % layer.Title())
+
+        # Determine which render function to use.
+        useraw, draw_func, draw_func_param = \
+                self.low_level_renderer(layer)
+        if verbose > 0 : log("Using draw_func %s\n"%(repr(draw_func)))
+
+        tool_cache = {}
+        
+        new_baseid=dc.SetBaseID(layer.title)
+        if new_baseid in self.used_baseids:
+            raise SVGMapWriterError(_("Clash of layer names!\n")+ \
+                _("Two layers probably have the same name, try renaming one."))
+        # prefix of a shape id to be unique
+        self.used_baseids.append(new_baseid)
+        # Titel of current layer to the groups meta informations
+        dc.BeginGroup(meta={'Layer':layer.Title(), })
+        # Delete all MetaData
+        dc.FlushMeta()
+        for shape in self.layer_shapes(layer):
+            if field is None:
+                group = defaultGroup
+                value = group.GetDisplayText()
+            else:
+                value = table.ReadValue(shape.ShapeID(), field)
+                group = lc.FindGroup(value)
+
+            if not group.IsVisible():
+                continue
+
+            # Render classification
+            shapeType = layer.ShapeType()
+            props = group.GetProperties()
+
+            # put meta infos into DC
+            if field and value:
+                dc.SetMeta({field:value, })
+            # set current shape id
+            dc.SetID(shape.ShapeID())
+
+            try:
+                pen, brush = tool_cache[id(group)]
+            except KeyError:
+                pen, brush = tool_cache[id(group)] \
+                             = self.tools_for_property(group.GetProperties())
+
+            if useraw:
+                data = shape.RawData()
+            else:
+                data = shape.Points()
+
+            if shapeType==SHAPETYPE_POINT:
+                draw_func(draw_func_param, data, pen, brush,
+                           size = group.GetProperties().GetSize())
+            elif shapeType==SHAPETYPE_ARC:
+            # do not fill the polylines in linestring layers
+                draw_func(draw_func_param, data, pen, TRANSPARENT_BRUSH)
+            else:
+                 draw_func(draw_func_param, data, pen, brush)
+            # compatibility
+            if 0:
+                yield True
+        # reset shape id
+        dc.SetID(-1)
+        dc.SetBaseID("")
+        dc.EndGroup()
+    
+    def draw_raster_layer(self, layer):
+        """Draw the raster layer"""
+        # TODO: For now we cannot draw raster layers onto our VirtualDC
+        log(_("Warning: Raster layer not written as " +
+              "svgexport does not support this yet!\n"))
+    
+    def draw_raster_data(self, data, format="BMP"):
+        """Draw the raster image in data onto the DC"""
+        # TODO: For now we cannot draw raster data onto our VirtualDC
+        pass
+    
+    def RenderMap(self, selected_layer, selected_shapes):
+        """Overriden to avoid automatic rendering of legend, 
+        scalbar and frame.
+        """
+        dc = self.dc
+        self.selected_layer = selected_layer
+        self.selected_shapes = selected_shapes
+        minx, miny, width, height = self.region
+        # scale down to a size of 1000
+        trans = Trafo()
+        trans.Append('scale', (1000.0 / ((width + height) / 2.0)))
+        #
+        dc.BeginClipPath('mapclip')
+        dc.DrawRectangle(0, 0, width, height)
+        dc.EndClipPath()
+        #
+        dc.BeginGroup(meta={'Object':'map', }, clipid='mapclip', \
+                transform=trans)
+        self.render_map()
+        dc.EndGroup()
+    
+
+class VirtualDC(XMLWriter):
+    """This class imitates a DC and writes SVG instead.
+    
+    All shapes and graphic objects will be turned into 
+    SVG elements and will be written into a file.
+    Any properties, such as stroke width or stroke color,
+    will be written together with the SVG elements.
+    """
+    def __init__(self, file, dim=(0,0), units=''):
+        """Setup some variables and objects for property collection."""
+        XMLWriter.__init__(self)
+        self.dim = dim
+        self.units = units
+        self.pen = {}
+        self.brush = {}
+        self.font = {}
+        self.meta = {}
+        self.style = {}
+        # Some buffers
+        self.points = []
+        self.id = -1
+        self.flush_meta = 1
+        self.write(file)
+    
+    def write_indent(self, str):
+        """Write a string to the file with the current indention level.
+        """
+        from Thuban.Model.xmlwriter import TAB
+        self.file.write("%s%s" % (TAB*self.indent_level, str))
+    
+    def AddMeta(self, key, val):
+        """Append some metadata to the array that will be
+        written with the next svg-element
+        """
+        if key is '' or val is '':
+            return
+        self.meta[key] = val
+    
+    def SetMeta(self, pairs, flush_after=1):
+        """Delete old meta informations and set the new ones."""
+        self.meta = {}
+        self.flush_meta = flush_after
+        for key, val in pairs.items():
+            self.AddMeta(key, val)
+    
+    def FlushMeta(self):
+        """Drop collected metadata."""
+        self.meta = {}
+
+    def BeginGroup(self, **args):
+        """Begin a group of elements.
+        
+        Possible arguments:
+            meta        A list of key, value metadata pairs
+            style       A list of key, value style attributes
+            clipid      The ID of a clipPath definition to be
+                        applied to this group
+        """
+        self.FlushMeta()
+        # adding meta data
+        if args.has_key('meta'):
+            for key, val in args['meta'].items():
+                self.AddMeta(key, val)
+        attribs = " "
+        # adding style attributes
+        if args.has_key('style'):
+            for key, val in args['style'].items():
+                attribs += '%s="%s" ' % (key, val)
+        # adding clip informations
+        if args.has_key("clipid"):
+            attribs += ' clip-path="url(#%s)"' % (args['clipid'],)
+            # FIXME: this shouldn't be static
+            attribs += ' clip-rule="evenodd"'
+        if args.has_key('transform'):
+            trafostr = self.parse_trafo(args['transform'])
+            if trafostr:
+                attribs += ' transform="%s"' % (trafostr)
+        # put everything together
+        self.write_indent('<g %s%s>\n' % (self.make_meta(), attribs))
+        self.indent_level += 1
+    
+    def parse_trafo(self, trafo):
+        """Examine a trafo object for asigned transformations details."""
+        if not trafo:
+            return ''
+        retval = ''
+        while trafo.Count() > 0:
+            trans, coeffs = tuple(trafo.Pop())
+            if isinstance(coeffs, ListType):
+                retval += " %s%s" % (trans, join(coeffs, ', '))
+            else: retval += " %s(%s)" % (trans, coeffs)
+        # return the string
+        return retval
+
+    def EndGroup(self):
+        """End a group of elements"""
+        self.indent_level -= 1
+        self.write_indent('</g>\n')
+        self.FlushMeta()
+
+    def BeginExport(self):
+        """Start the export process and write basic document
+        informations to the file.
+        """
+        self.write_indent('<?xml version="1.0" encoding="ISO-8859-1" '
+            'standalone="yes"?>\n')
+        width, height = self.dim
+        self.write_indent('<svg>\n')
+        self.indent_level += 1
+    
+    def EndExport(self):
+        """End the export process with closing the SVG tag and close
+        the file accessor"""
+        self.indent_level -= 1
+        self.write_indent('</svg>\n')
+        self.close()
+    
+    def Close(self):
+        """Close the file."""
+        self.close()
+    
+    def BeginDrawing(self):
+        """Dummy function to work with the Thuban renderers."""
+        pass
+        
+    def EndDrawing(self):
+        """Dummy function to work with the Thuban renderers."""
+        pass
+    
+    def GetSizeTuple(self):
+        """Return the dimension of this virtual canvas."""
+        return self.dim
+    
+    def GetTextExtent(self, text):
+        """Return the dimension of the given text."""
+        # FIXME: find something more appropriate
+        try:
+            if self.font:
+                return (int(self.font["font-size"]), 
+                        len(text) * int(self.font["font-size"]))
+            else: return (12,len(text) * 10)
+        except ValueError:
+            return (12,len(text) * 10)
+    
+
+    def SetBaseID(self, id):
+        """Set first part of ID stored by the svg elements. Return it.
+
+        Will be used in make_id() as first part of an XML attribute "id".
+        The second part is set by SetID().
+        Check comments at make_id().
+
+        We might add an abritrary "t" for thuban if the parameter
+        starts with XML, which is not allowed in XML 1.0.
+
+        We need to ensure that all characters are okay as XML id attribute.
+        As there seem no easy way in Python (today 20040925) to check
+        for compliance with XML 1.0 character classes like NameChar,
+        we use Python's string method isalnum() as approximation.
+        (See http://mail.python.org/pipermail/xml-sig/2002-January/006981.html
+        and xmlgenchar.py. To be better we would need to hold our own
+        huge table of allowed unicode characters.
+        FIXME if python comes with a better funcation for XML 1.0 NameChar)
+
+        Characters that are not in our approx of NameChar get transformed
+        get escaped to their hex value. 
+        """
+        # an ID Name shall not start with xml.
+        if id[0:3].lower() == "xml":
+            id = "t" + id
+
+        self.baseid = ""
+        for c in id:
+            if c.isalnum() or c in ".-_":
+                self.baseid += c
+            else:
+                self.baseid += binascii.b2a_hex(c)
+        return self.baseid
+
+    def SetID(self, id):
+        """Set second part of ID stored by the svg elements.
+
+        Will be used in make_id() as first part of an XML attribute "id".
+        Only set this to positive integer numbers.
+        Read comments at SetBaseID() and make_id().
+        """
+        self.id = id
+
+    def SetFont(self, font):
+        """Set the fontproperties to use with text elements."""
+        if font is not None:
+            fontname = font.GetFaceName()
+            size = font.GetPointSize()
+            for svgfont, pattern in fontMap.items():
+                if pattern.match(fontname):
+                    fontname = svgfont
+                    break
+            if fontname:
+                self.font["font-family"] = fontname
+            else: self.font["font-family"] = None
+            if size:
+                self.font["font-size"] = str(size)
+            else: self.font["font-size"] = None
+    
+    def SetPen(self, pen):
+        """Set the style of the pen used to draw graphics."""
+        if pen is TRANSPARENT_PEN:
+            self.pen = {}
+        else:
+            self.pen["stroke"] = pen.GetColor().hex()
+            self.pen["stroke-dasharray"] = join(pen.GetDashes(), ',')
+            self.pen["stroke-width"] = pen.GetWidth()
+            self.pen["stroke-linejoin"] = svg_joins[pen.GetJoin()]
+            self.pen["stroke-linecap"] = svg_caps[pen.GetCap()]
+    
+    def SetBrush(self, brush):
+        """Set the fill properties."""
+        if brush is TRANSPARENT_BRUSH:
+            self.brush['fill'] = 'none'
+        elif brush.GetPattern() is SOLID:
+            self.brush['fill'] = brush.GetColor().hex()
+        else: # TODO Handle Patterns
+            pass
+    
+    def SetTextForeground(self, color):
+        """Set the color of the text foreground."""
+        self.font['fill'] = color.hex()
+        
+    def make_style(self, line=0, fill=0, font=0):
+        """Build the style attribute including desired properties
+        such as fill, forground, stroke, etc."""
+        result = []
+        # little helper function
+        def append(pairs):
+            for key, val in pairs.items():
+                if not val in [None, '']:
+                    result.append('%s:%s' % (key, val))
+        #
+        if line and len(self.pen) > 0:
+                append(self.pen)
+        if fill and len(self.brush) > 0:
+                append(self.brush)
+        if font and len(self.font) > 0:
+                append(self.font)
+        style = join(result, '; ')
+        if style:
+            return 'style="%s"' % (style, )
+        else:
+            return ''
+    
+    def make_meta(self, meta=None):
+        """Build the meta attribute."""
+        result = []
+        if not meta:
+            meta = self.meta
+        if len(meta) is 0:
+            return ''
+        for key, val in meta.items():
+            if not val in [None, '', 'none']:
+                result.append('%s:%s' % (key, val))
+        if self.flush_meta:
+            self.meta = {}
+        return 'meta="%s"' % (join(result, '; '))
+    
+    def make_id(self):
+        """Return id= string for object out of currently set baseid and id.
+        
+        Return the empty string if no id was set.
+
+        In an XML file each id should be unique 
+        (see XML 1.0 section 3.3.1 Attribute Types, Validity constraint: ID)
+        So this function should only return a unique values.
+        which also coforms to the the XML "Name production" (section 3.2).
+
+        For this it completely depends 
+        on what has been set by SetBaseID() and SetID().
+        Only call this function if you have called them w unique values before
+        (or negative x in SetID(x) to get an empty result)
+        Will raise SVGMapWriterError if SetID value cannot be converted to %d.
+
+        A check of uniqueness in this function might be time consuming,
+        because it would require to hold and search through a complete table.
+        """
+        if self.id < 0:
+            return ''
+        try:
+            id= 'id="%s_%d"' % (self.baseid, self.id)
+        except TypeError, inst:
+            raise SVGMapWriterError(_("Internal make_id() failure: ") \
+                        + repr(inst))
+        return id
+
+    def DrawEllipse(self, x, y, dx, dy):
+        """Draw an ellipse."""
+        elips = '<ellipse cx="%s" cy="%s" rx="%s" ry="%s" %s %s %s/>\n'
+        self.write_indent(elips % (x, y, dx, dy, self.make_id(),
+                self.make_style(1,1,0), self.make_meta()) )
+    
+    def DrawCircle(self, x, y, radius):
+        """Draw a circle onto the virtual dc."""
+        self.write_indent('<circle cx="%s" cy="%s" r="%s" %s %s %s/>\n' %
+                (x, y, radius, self.make_id(), self.make_style(1,1,0), 
+                self.make_meta()) )
+    
+    def DrawRectangle(self, x, y, width, height):
+        """Draw a rectangle with the given parameters."""
+        rect = '<rect x="%s" y="%s" width="%s" height="%s" %s %s %s/>\n'
+        self.write_indent(rect %  ( x, y, width, height, self.make_id(), 
+            self.make_style(1,1,0), self.make_meta()) )
+
+    def DrawText(self, text, x, y):
+        """Draw Text at the given position."""
+        beginText = '<text x="%s" y="%s" %s %s %s>'
+        self.write_indent(beginText %  ( x, y, self.make_id(), 
+            self.make_style(0,0,1), self.make_meta()) )
+        self.file.write(escape(text))
+        self.file.write('</text>\n')
+    
+    def DrawLines(self, points):
+        """Draw some points into a Buffer that will be 
+        written before the next object.
+        """
+        self.DrawPolygonPath([points], closed=False)
+    
+    def DrawPolygonPath(self, polys, closed=True):
+        """Draw a list of polygons or polylines as one SVG path.
+
+        Parameter:
+        polys    list of poly- gons/lines; each consisting of a list of points
+        closed   Boolean; optional; Default: True
+                 False will leave each subpath open thus making it polylines.
+        """
+        self.write_indent('<path %s ' % (self.make_style(1,1,0)))
+        data = []
+        for poly in polys:
+            i = 0
+            for point in poly:
+                if i is 0:
+                    data.append('\nM %s %s' % (point.x, point.y))
+                    i+=1
+                else:
+                    # SVG 1.1 Spec 8.3.1 recommends that lines length <= 255
+                    # we make a best effort in throwing in a few newlines
+                    data.append('\nL %s %s' % (point.x, point.y))
+            if closed:
+                data.append(' Z')
+
+        # Put everything together and write it to the file
+        self.file.write('%s %s d="%s"/>\n' % (self.make_id(), 
+            self.make_meta(), join(data, '') ) )
+
+    def DrawSpline(self, points, closed=0):
+        """Calculate square bezier points for an xfig approximated spline.
+
+        DrawSpline() needs to do the same as the function of the Device Context
+        of wxWidgets. Code inspection shows it uses the "approximated
+        splines" of xfig <= 3.1. This can be mapped 
+        on SVG's squared bezier curves,
+        by doing the same calculation like wxPostScriptDC::DoDrawSpline() in
+        wxWidgets src/generic/dcpsg.cpp.
+        Which is derived from xfig's 3.1.4 u_draw.c(draw_open_spline()).
+
+        And then leave out the last translation to cubic beziers
+        done in the postscript code of DrawSplineSection.
+        """
+        self.write_indent('<path %s ' % (self.make_style(1,1,0)))
+        datastr = ""
+
+        x1=points[0].x
+        y1=points[0].y
+
+        datastr+=('M %s %s ' % (x1, y1))
+
+        c=points[1].x
+        d=points[1].y
+
+        x3  = (x1 + c) / 2;
+        y3  = (y1 + d) / 2;
+
+        datastr+=('L %s %s ' % (x3,y3))
+
+        for point in points[2:]:
+            x2 = c
+            y2 = d
+            c = point.x
+            d = point.y
+            x3 = (x2 + c) / 2;
+            y3 = (y2 + d) / 2;
+
+            # With SVG's bezier commands, the last point becomes the next start
+            # so no new L necessary
+            # SVG Spec 1.1 recommends to not uses lines longer than 255 chars
+            datastr+=('Q %s %s %s %s\n' % (x2,y2,x3,y3))
+
+        datastr+=('L %s %s' % (c,d))
+
+        self.file.write('%s %s d="%s"/>\n' % (self.make_id(), 
+            self.make_meta(), datastr ) )
+
+    def BeginClipPath(self, id):
+        """Build a clipping region to draw in."""
+        self.write_indent('<clipPath id="%s">\n' % id)
+        self.indent_level += 1
+
+    def EndClipPath(self):
+        """End a clip path."""
+        self.indent_level -= 1
+        self.write_indent("</clipPath>\n")

Added: packages/thuban/branches/upstream/current/Extensions/svgexport/svgsaver.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/svgexport/svgsaver.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/svgexport/svgsaver.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,105 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Markus Rechtien <markus at intevation.de> (2004)
+# Bernhard Herzog <bh at intevation.de> (2004)
+# Bernhard Reiter <bernhard at intevation.de> (2004)
+# Jan-Oliver Wagner <jan at intevation.de> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2721 $"
+# $Source$
+# $Id: svgsaver.py 2721 2007-01-13 15:11:42Z dpinte $
+
+
+"""
+Classes to write a session in SVG format
+"""
+
+
+# Needed wx.-toolkit classes
+import wx
+
+# We need os.path
+import os
+
+# use _() already now for all strings that may later be translated
+from Thuban import _
+
+# Import SVG related classes
+from svgmapwriter import VirtualDC, SVGRenderer, SVGMapWriterError
+
+
+def write_to_svg(context):
+    '''Export data depending on the set properties.
+
+    This is the main export funcation.
+    '''
+    canvas = context.mainwindow.canvas
+    file = None
+    map = canvas.Map()
+    
+    if hasattr(canvas, "export_path"):
+        export_path = canvas.export_path
+    else:
+        export_path="."
+    # Get the file the session shall be written to
+    dlg = wx.FileDialog(canvas, _("Write SVG"), export_path, "", 
+            "Scalable Vector Graphics (*.svg)|*.svg", 
+            wx.SAVE|wx.OVERWRITE_PROMPT)
+    
+    response = dlg.ShowModal()
+    if response == wx.ID_OK:
+        file = dlg.GetPath()
+    else: # Do nothing if choice was interrupted.
+        return 0
+        
+    # If the user selected a file
+    if file and map is not None:
+        canvas.export_path = os.path.dirname(file)
+        # Initialize some dimensions and calculate the map bounds
+        width, height = canvas.GetSizeTuple()
+        llx, lly = canvas.win_to_proj(0, height)
+        urx, ury = canvas.win_to_proj(width, 0)
+        mapwidth, mapheight = ((urx - llx), (ury - lly))
+        mapregion = (llx, lly, mapwidth, mapheight)
+        
+        # Get all selected layers and shapes that should be written as SVG
+        selected_layer = canvas.selection.SelectedLayer()
+        selected_shapes = canvas.selection.SelectedShapes()
+        try:
+            dc = VirtualDC(file, (mapwidth, mapheight, ))
+            dc.BeginExport()
+            # map scale offset region
+            renderer = SVGRenderer(dc, map, 1.0, (0 - min(llx, urx),
+                    0 + max(lly, ury)), mapregion)
+            # Render the map
+            renderer.RenderMap(selected_layer, selected_shapes)
+            dc.EndExport()
+        except SVGMapWriterError, inst:
+            context.mainwindow.RunMessageBox(_("Error: SVG not written!"),
+                text=_("Could not write SVG because: ")+ str(inst),
+                flags= wx.OK | wx.ICON_HAND)
+            # delete partly writting file
+            os.remove(file)
+
+
+
+# Thuban has named commands which can be registered in the central
+# instance registry.
+from Thuban.UI.command import registry, Command
+
+# The instance of the main menu of the Thuban application
+# See Thuban/UI/menu.py for the API of the Menu class
+from Thuban.UI.mainwindow import main_menu
+
+# create a new command and register it
+registry.Add(Command('write_to_svg', _('Write SVG Map'), write_to_svg,
+                     helptext = _('Export the a map into a SVG file')))
+
+# find the menu we want to be in (create it anew if not found)
+menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))
+
+# finally bind the new command with an entry in the extensions menu
+menu.InsertItem('write_to_svg')

Added: packages/thuban/branches/upstream/current/Extensions/svgexport/test/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/svgexport/test/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/svgexport/test/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,6 @@
+# Copyright (C) 2004 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.

Added: packages/thuban/branches/upstream/current/Extensions/svgexport/test/test_svgmapwriter.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/svgexport/test/test_svgmapwriter.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/svgexport/test/test_svgmapwriter.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,482 @@
+# Copyright (c) 2004,2005 by Intevation GmbH
+# Authors:
+# Markus Rechtien <markus at intevation.de> (2004)
+# Bernhard Reiter <bernhard at intevation.de> (2004,2005)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Test the svgexport."""
+
+__version__ = "$Revision: 2671 $"
+# $Source$
+# $Id: test_svgmapwriter.py 2671 2005-10-17 20:10:18Z bernhard $
+
+
+import os
+import sys
+import string
+import StringIO
+import unittest
+
+# If run directly as a script, add Thuban's test directory to the path.
+# Otherwise we assume that the importing code has already done it.
+if __name__ == "__main__":
+    sys.path.append(os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])),
+                                 "..", "..", "..", "test"))
+from mockgeo import SimpleShapeStore
+import support
+support.initthuban()
+
+# Now import needed SVG stuff
+from Extensions.svgexport.svgmapwriter import VirtualDC, \
+     Pen, Brush, SOLID,  Point, Font, TRANSPARENT_PEN, TRANSPARENT_BRUSH, \
+     SVGRenderer, SVGMapWriterError
+# Color related classes from the model of thuban
+from Thuban.Model.color import Color, Black, Transparent
+
+from Thuban.Model.data import SHAPETYPE_ARC, SHAPETYPE_POLYGON
+from Thuban.Model.map import Map
+from Thuban.Model.layer import BaseLayer, Layer
+from Thuban.Model.table import MemoryTable, \
+     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING
+
+
+
+# We use xmlsupport to verify the SVG output
+import xmlsupport
+
+class BaseTestWithDC(unittest.TestCase):
+    """Add dc creation and self.to_destroy list to setUp() and tearDown().
+
+    This is a baseclass for tests needing a dc.
+    """
+    def setUp(self):
+        """Create dc for testing and set up self.to_destroy.
+
+        Test should put all objects whose Destroy 
+        should be called at unittest.main
+        the end into this list so that they're destroyed in tearDown
+        """
+        self.to_destroy = []
+
+        self.file = StringIO.StringIO()
+        self.dc = VirtualDC(self.file)
+
+    def tearDown(self):
+        for obj in self.to_destroy:
+            obj.Destroy()
+
+
+class BaseTestWithDCtools(BaseTestWithDC):
+    """Add standard colors and polygon to setUp() for DC tests."""
+    def setUp(self):
+        """Initialize tools."""
+        BaseTestWithDC.setUp(self)
+        self.black = Black
+        self.solid_pen = Pen(Color(1.0, 0.0, 1.0), 3, SOLID)
+        self.trans_pen = TRANSPARENT_PEN
+        self.solid_brush = Brush(Color(0.0, 1.0, 0.0), SOLID)
+        self.trans_brush = TRANSPARENT_BRUSH
+        self.polygon = [Point(5.6,5.5), Point(95.4,5.3), Point(95.2,95.1),
+                Point(5.0,95.0), Point(5.0,5.0)]
+        self.meta = {"Object":"test", "Label":"nothing"}
+        self.font = Font("Helvetica", 12)
+
+
+class TestVirtualDC(BaseTestWithDCtools):
+    '''Test VirtualDC imitating a wxDC and writing SVGRenderer instead.'''
+
+    def test_clippath(self):
+        '''Define a clipping region and close it afterwards.'''
+        data = '<clipPath id="testid">\n</clipPath>'
+        self.dc.BeginClipPath('testid')
+        self.dc.EndClipPath()
+        self.assertEquals(xmlsupport.sax_eventlist(data=data),
+                          xmlsupport.sax_eventlist(data=self.file.getvalue()))
+
+    def test_polygon_closed(self):
+        '''Set drawing properties and draw a polygon onto the dc.'''
+        data = ('<path style="stroke-linejoin:round; stroke:#ff00ff; '
+                'stroke-width:3; stroke-linecap:round; fill:#00ff00" ' 
+                'meta="Object:test; Label:nothing" d="\nM 5.6 5.5 '
+                'L 95.4 5.3 L 95.2 95.1 L 5.0 95.0 L 5.0 5.0 Z"/>')
+        dc = self.dc
+        dc.SetPen(self.solid_pen)
+        dc.SetMeta(self.meta)
+        dc.SetBrush(self.solid_brush)
+        dc.DrawPolygonPath([self.polygon])
+        self.assertEquals(xmlsupport.sax_eventlist(data=data), 
+                          xmlsupport.sax_eventlist(data=self.file.getvalue()))
+    
+    def test_polyline(self):
+        '''Set drawing properties and draw a polyline onto the dc.'''
+        data = ('<path style="stroke-linejoin:round; stroke:#ff00ff; '
+                'stroke-width:3; stroke-linecap:round; fill:#00ff00" ' 
+                'meta="Object:test; Label:nothing" d="\nM 5.6 5.5'
+                '\nL 95.4 5.3\nL 95.2 95.1\nL 5.0 95.0\nL 5.0 5.0"/>')
+        dc = self.dc
+        dc.SetPen(self.solid_pen)
+        dc.SetMeta(self.meta)
+        dc.SetBrush(self.solid_brush)
+        dc.DrawPolygonPath([self.polygon], closed=False)
+        self.assertEquals(xmlsupport.sax_eventlist(data=data), 
+                          xmlsupport.sax_eventlist(data=self.file.getvalue()))
+
+    def test_transparent_polyline(self):
+        '''Test dc drawing a transparent polyline.'''
+        data = ('<path style="stroke-linejoin:round; stroke:#ff00ff; '
+                'stroke-width:3; stroke-linecap:round; fill:none" ' 
+                'meta="Object:test; Label:nothing" d="\nM 5.6 5.5'
+                ' L 95.4 5.3\nL 95.2 95.1\nL 5.0 95.0\nL 5.0 5.0"/>')
+        dc = self.dc
+        dc.SetPen(self.solid_pen)
+        dc.SetMeta(self.meta)
+        dc.SetBrush(self.trans_brush)
+        dc.DrawPolygonPath([self.polygon], closed=False)
+        self.assertEquals(xmlsupport.sax_eventlist(data=data), 
+                          xmlsupport.sax_eventlist(data=self.file.getvalue()))
+
+    def test_polygon_with_hole(self):
+        '''Set drawing properties and draw a polygon onto the dc.'''
+
+        holepolygon = [Point(11.1,11.1), Point(33.3,11.1), Point(22.2,22.2),
+                Point(11.1,11.1)]
+        data = ('<path style="stroke-linejoin:round; stroke:#ff00ff; '
+                'stroke-width:3; stroke-linecap:round; fill:#00ff00" ' 
+                'meta="Object:test; Label:nothing" d="\nM 5.6 5.5 '
+                'L 95.4 5.3 L 95.2 95.1 L 5.0 95.0 L 5.0 5.0 Z'
+                '\nM 11.1 11.1 L 33.3 11.1 L 22.2 22.2 L 11.1 11.1 Z"/>')
+
+        dc = self.dc
+        dc.SetPen(self.solid_pen)
+        dc.SetMeta(self.meta)
+        dc.SetBrush(self.solid_brush)
+        dc.DrawPolygonPath([self.polygon, holepolygon])
+        self.assertEquals(xmlsupport.sax_eventlist(data=data), 
+                          xmlsupport.sax_eventlist(data=self.file.getvalue()))
+
+    def test_rect(self):
+        '''Set drawing properties and draw a rectangle'''
+        data = ('<rect x="5.5" y="5.4" width="90.3" height="90.2" '
+                'style="stroke-linejoin:round; stroke:#ff00ff; '
+                'stroke-width:3; stroke-linecap:round; fill:none" '
+                'meta="Object:test; Label:nothing"/>')
+        dc = self.dc
+        dc.SetPen(self.solid_pen)
+        dc.SetMeta(self.meta)
+        dc.SetBrush(self.trans_brush)
+        dc.DrawRectangle(5.5, 5.4, 90.3, 90.2)
+        self.assertEquals(xmlsupport.sax_eventlist(data=data), 
+                          xmlsupport.sax_eventlist(data=self.file.getvalue()))
+
+    def test_circle(self):
+        '''Set drawing properties and draw a circle'''
+        data = ('<circle cx="5.5" cy="5.3" r="90.1"  style="'
+                'fill:#00ff00" meta="Object:test; Label:nothing"/>')
+        dc = self.dc
+        dc.SetPen(self.trans_pen)
+        dc.SetMeta(self.meta)
+        dc.SetBrush(self.solid_brush)
+        dc.DrawCircle(5.5, 5.3, 90.1)
+        self.assertEquals(xmlsupport.sax_eventlist(data=data),
+                          xmlsupport.sax_eventlist(data=self.file.getvalue()))
+
+    def test_ellipse(self):
+        '''Set drawing properties and draw a circle'''
+        data = ('<ellipse cx="5.5" cy="5.3" rx="90.1" ry="100.321"  style="'
+                'fill:#00ff00" meta="Object:test; Label:nothing"/>')
+        dc = self.dc
+        dc.SetPen(self.trans_pen)
+        dc.SetMeta(self.meta)
+        dc.SetBrush(self.solid_brush)
+        dc.DrawEllipse(5.5, 5.3, 90.1, 100.321)
+        self.assertEquals(xmlsupport.sax_eventlist(data=data), 
+                          xmlsupport.sax_eventlist(data=self.file.getvalue()))
+
+    def test_text(self):
+        '''Set drawing properties and draw a circle'''
+        data = ('<text x="123.321" y="1515.5151" style="font-size:12; '
+                'font-family:Helvetica; fill:#000000" >Some text.</text>')
+        dc = self.dc
+        dc.SetTextForeground(self.black)
+        dc.SetFont(self.font)
+        dc.DrawText('Some text.', 123.321, 1515.5151)
+        self.assertEquals(xmlsupport.sax_eventlist(data=data),
+                          xmlsupport.sax_eventlist(data=self.file.getvalue()))
+
+    def test_document(self):
+        '''Set up a document with a dimension and 
+        latin encoding'''
+        data = ('<?xml version="1.0" encoding="ISO-8859-1" standalone'
+                '="yes"?>\n<svg>\n</svg>')
+        self.dc.BeginExport()
+        self.dc.EndExport()
+        self.assertEquals(xmlsupport.sax_eventlist(data=data), 
+                          xmlsupport.sax_eventlist(data=self.file.getvalue()))
+
+class TestDrawSplines(BaseTestWithDCtools):
+    """Testing DrawSpline variations.
+    See comments in DrawSpline().
+    """
+
+    def setUp(self):
+        BaseTestWithDCtools.setUp(self)
+        self.dataframe = ('<path style="stroke-linejoin:round; stroke:#ff00ff; '
+                'stroke-width:3; stroke-linecap:round; fill:none" ' 
+                'meta="Object:test; Label:nothing" d="%s"/>')
+
+        self.file = StringIO.StringIO()
+        self.dc = VirtualDC(self.file)
+        self.dc.SetPen(self.solid_pen)
+        self.dc.SetMeta(self.meta)
+        self.dc.SetBrush(self.trans_brush)
+
+    def test_drawspline3(self):
+        '''Test DrawSpline with three points in a row.'''
+
+        d=('M 10 10 L 12.55 12.55 Q 15.1 15.1 17.65 17.65\nL 20.2 20.2')
+        data=(self.dataframe % d)
+
+        self.dc.DrawSpline([ Point(10, 10),
+                        Point(15.1, 15.1),
+                        Point(20.2, 20.2) ])
+        #print file.getvalue()
+        self.assertEquals(xmlsupport.sax_eventlist(data = data),
+                          xmlsupport.sax_eventlist(data = self.file.getvalue()))
+
+    def test_drawspline4(self):
+        '''Test DrawSpline with four points in a row.'''
+
+        d='M 0 0 L 0 1 Q 0 2 0 3\nQ 0 4 0 5\nL 0 6'
+        data=(self.dataframe % d)
+
+        self.dc.DrawSpline([ Point(0, 0),
+                        Point(0, 2),
+                        Point(0, 4),
+                        Point(0, 6) ])
+        #print file.getvalue()
+        self.assertEquals(xmlsupport.sax_eventlist(data = data),
+                          xmlsupport.sax_eventlist(data = self.file.getvalue()))
+
+
+
+class TestSVGRendererIDHandling(BaseTestWithDC):
+
+    def test_make_id_nonintegersetid(self):
+        """Test that exception is raised when SetID was called with chars."""
+        dc=self.dc
+        dc.SetBaseID("a")
+        dc.SetID("abc")
+        self.assertRaises(SVGMapWriterError, dc.make_id)
+
+    def test_make_ide_nosetbaseid(self):
+        """Test as no setbaseid results in valid XML id starting with '_'."""
+        dc=self.dc
+        dc.SetBaseID("")
+        dc.SetID(123)
+        id=dc.make_id() # returns 'id="xxxxxx"'
+        self.assert_(id[4]=='_' or (id[4] in string.ascii_letters))
+
+    def test_xml_id_constraints(self):
+        """Test the checks for the XML id contraints by trying bad id parts."""
+
+        dc=self.dc
+        dc.SetID(42)
+
+        # an xml Name shall better not start with "xml" (case insensitive)
+        dc.SetBaseID("xml") 
+        id=dc.make_id() # returns 'id="xxxxxx"'
+        self.assert_(id[4:7].lower() != "xml")
+
+        dc.SetBaseID("XmL") 
+        id=dc.make_id()
+        self.assert_(id[4:7].lower() != "xml")
+
+        # recommended to better not use ":"
+        dc.SetBaseID("abc:def")
+        id=dc.make_id()
+        self.assert_(":" not in id )
+
+        # an XML name shall only have:
+        #    Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender
+        dc.SetBaseID("abc def")
+        id=dc.make_id()
+        self.assert_(" " not in id )
+
+        dc.SetBaseID("ab!cd")
+        id=dc.make_id()
+        self.assert_("!" not in id )
+
+        dc.SetBaseID("a.b-c_d")
+        id=dc.make_id()
+        self.assert_(id[4:11]=="a.b-c_d")
+
+
+    def test_make_id(self):
+        """Check "layer" and "layer1" do not clash; given integer ShapeIDs.
+        """
+        dc=self.dc
+        dc.SetBaseID("layer")
+        dc.SetID(10)
+        id1=dc.make_id()
+        dc.SetBaseID("layer1")
+        dc.SetID(0)
+        id2=dc.make_id()
+
+        self.assertNotEqual(id1,id2)
+
+
+    def test_check_for_layer_name_clash(self):
+        '''Create 2 layers with same name, try to write and check exception.
+        '''
+
+        # BaseLayer is not enough, because BaseRenderer.render_map()
+        # checks on isinstance of Layer not BaseLayer.
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0)])
+        shapes = [[[(0, 0), (10, 10)]]]
+        store = SimpleShapeStore(SHAPETYPE_ARC, shapes, table)
+
+        map = Map("TestLayerNameClash")
+        self.to_destroy.append(map)
+        layer=Layer("Same Name", store)
+        map.AddLayer(layer)
+        # reusing the same store with the same table and shapes should be okay
+        layer=Layer("Same Name", store)
+        map.AddLayer(layer)
+
+        renderer = SVGRenderer(self.dc, map,
+                    scale=1.0, offset=(0,0), region=(0,0,10,10))
+
+        self.assertRaises(SVGMapWriterError,
+                renderer.RenderMap, None, None)
+
+class TestSVGRenderer(BaseTestWithDC):
+    """Test methods of SVGRenderer."""
+
+    def test_label_font(self):
+        """Test that label_font used the self.factor."""
+        mockmap = Map("mock title")
+        self.to_destroy.append(mockmap)
+        renderer = SVGRenderer(self.dc, mockmap,
+                    scale=1.0, offset=(0,0), region=(0,0,30000,30000))
+        #print renderer.factor
+        self.assertEqual( renderer.label_font().GetPointSize(),
+                          12*renderer.factor
+                        )
+
+class Testobjectexport(BaseTestWithDC):
+
+    def test_transparent_polygon(self):
+        """Create layer with non-filled polygon and test svg rendering."""
+
+        data = ('<clipPath id="mapclip">\n'
+                '    <rect x="0" y="0" width="10" height="10"   />\n'
+                '</clipPath>\n'
+                '<g meta="Object:map"  clip-path="url(#mapclip)" '
+                'clip-rule="evenodd" transform=" scale(100.0)">\n'
+                '    <g meta="Layer:P-Layer" >\n'
+                '        <path style="stroke-linejoin:round; stroke:#000000; '
+                'stroke-width:0.01; stroke-linecap:round; fill:none" '
+                'id="P-Layer_0"'
+                '  d="\nM 0.0 0.0\nL 10.0 -10.0\nL 0.0 -10.0\nL 0.0 0.0 Z"/>\n'
+                '    </g>\n</g>\n')
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0)])
+        shapes = [[[(0, 0), (10, 10), (0, 10), (0, 0) ]]]
+        store = SimpleShapeStore(SHAPETYPE_POLYGON, shapes, table)
+
+        map = Map("testpolygonexport")
+        self.to_destroy.append(map)
+        layer=Layer("P-Layer", store, fill=Transparent)
+        map.AddLayer(layer)
+
+        renderer = SVGRenderer(self.dc, map,
+                    scale=1.0, offset=(0,0), region=(0,0,10,10))
+        renderer.RenderMap(None, None)
+        #print (data)
+        #print (self.dc.file.getvalue())
+        self.assertEquals(data, self.dc.file.getvalue())
+
+    def test_export_polygon_with_hole(self):
+        """ Create layer with polygon ans hole and test svg rendering."""
+
+        data = ('<clipPath id="mapclip">\n'
+                '    <rect x="0" y="0" width="10" height="10"   />\n'
+                '</clipPath>\n'
+                '<g meta="Object:map"  clip-path="url(#mapclip)" '
+                'clip-rule="evenodd" transform=" scale(100.0)">\n'
+                '    <g meta="Layer:P-Layer" >\n'
+                '        <path style="stroke-linejoin:round; stroke:#000000; '
+                'stroke-width:0.01; stroke-linecap:round; fill:none" '
+                'id="P-Layer_0"'
+                '  d="\nM 0.0 0.0\nL 0.0 -10.0\nL 10.0 -10.0\nL 0.0 0.0 Z'
+                '\nM 5.0 -6.0\nL 5.0 -7.0\nL 4.0 -7.0\nL 4.0 -6.0'
+                '\nL 5.0 -6.0 Z"/>\n'
+                '    </g>\n</g>\n')
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0)])
+        shapes = [[[(0, 0), (0, 10), (10, 10), (0, 0) ],
+                   [(5, 6), (5,  7), ( 4,  7), (4, 6), (5, 6)]
+                 ]]
+        store = SimpleShapeStore(SHAPETYPE_POLYGON, shapes, table)
+
+        map = Map("testpolygonexport")
+        self.to_destroy.append(map)
+        layer=Layer("P-Layer", store, fill=Transparent)
+        map.AddLayer(layer)
+
+        renderer = SVGRenderer(self.dc, map,
+                    scale=1.0, offset=(0,0), region=(0,0,10,10))
+        renderer.RenderMap(None, None)
+        #print (data)
+        #print (self.dc.file.getvalue())
+        self.assertEquals(data, self.dc.file.getvalue())
+
+    def test_export_arc_no_fill(self):
+        """Create layer with a linestring and test svg rendering.
+
+	Even when the layer or the classifications have a fill color,
+	the resulting path shall not be filled for an ARC (linestring) layer.
+	"""
+
+        data = ('<clipPath id="mapclip">\n'
+                '    <rect x="0" y="0" width="10" height="10"   />\n'
+                '</clipPath>\n'
+                '<g meta="Object:map"  clip-path="url(#mapclip)" '
+                'clip-rule="evenodd" transform=" scale(100.0)">\n'
+                '    <g meta="Layer:A-Layer" >\n'
+                '        <path style="stroke-linejoin:round; stroke:#000000; '
+                'stroke-width:0.01; stroke-linecap:round; fill:none" '
+                'id="A-Layer_0"'
+                '  d="\nM 0.0 0.0\nL 2.0 -8.0\nL 10.0 -10.0"/>\n'
+                '    </g>\n</g>\n')
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0)])
+        shapes = [[[(0, 0), (2, 8), (10, 10) ]]]
+        store = SimpleShapeStore(SHAPETYPE_ARC, shapes, table)
+
+        map = Map("testarcexport")
+        self.to_destroy.append(map)
+        layer=Layer("A-Layer", store, fill=Black)
+        map.AddLayer(layer)
+
+        renderer = SVGRenderer(self.dc, map,
+                    scale=1.0, offset=(0,0), region=(0,0,10,10))
+        renderer.RenderMap(None, None)
+        #print (data)
+        #print (self.dc.file.getvalue())
+        self.assertEquals(data, self.dc.file.getvalue())
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/Extensions/svgexport/x.diff
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/svgexport/x.diff	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/svgexport/x.diff	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,52 @@
+Index: svgmapwriter.py
+===================================================================
+--- svgmapwriter.py	(Revision 2721)
++++ svgmapwriter.py	(Arbeitskopie)
+@@ -326,11 +326,11 @@
+                 data = shape.Points()
+ 
+             if shapeType==SHAPETYPE_POINT:
+-            	draw_func(draw_func_param, data, pen, brush,
++                draw_func(draw_func_param, data, pen, brush,
+                            size = group.GetProperties().GetSize())
+             elif shapeType==SHAPETYPE_ARC:
+-	    	# do not fill the polylines in linestring layers
+-            	draw_func(draw_func_param, data, pen, TRANSPARENT_BRUSH)
++            # do not fill the polylines in linestring layers
++                draw_func(draw_func_param, data, pen, TRANSPARENT_BRUSH)
+             else:
+                  draw_func(draw_func_param, data, pen, brush)
+             # compatibility
+@@ -380,7 +380,7 @@
+     All shapes and graphic objects will be turned into 
+     SVG elements and will be written into a file.
+     Any properties, such as stroke width or stroke color,
+-    will be written together with the SVG elementents.
++    will be written together with the SVG elements.
+     """
+     def __init__(self, file, dim=(0,0), units=''):
+         """Setup some variables and objects for property collection."""
+Index: TODO
+===================================================================
+--- TODO	(Revision 2726)
++++ TODO	(Arbeitskopie)
+@@ -4,6 +4,19 @@
+ 
+ * Enable Raster file export.
+ 
++Spec REC-SVG11-20030114 includes no indication about embedding raster images.
++Thus we probably have to write extra files.
++	
++	Substeps:
++		a) write shown raster file as .png, no matter which
++		   filename.
++		b) add filename construction based on used svg file.
++		   (There can be several raster layers.)
++		c) add <image> tag to .svg file
++	Open Questions:
++		q1) What resolution to use for the PNG file?
++		q2) Should be there one PNG file or is tiling better?
++
+ For 1.0.x, x>2:
+ 
+ * find out why the memory shapes in class Testobjectexport

Added: packages/thuban/branches/upstream/current/Extensions/umn_mapserver/README
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/umn_mapserver/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/umn_mapserver/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,103 @@
+
+UMN MapServer Extension for Thuban
+===================================
+
+   *** ATTENTION: ***
+
+   The installation instructions here are detailed, so I hope everybody
+   can install the extension. People who are experienced will know
+   most of the commands, but everybody should be able to use
+   this extension.
+
+
+
+Summary
+--------------------
+
+This extension for Thuban allows you to handle UMN MapServer .map-files.
+
+
+
+Requirements
+--------------------
+
+To use the UMN MapServer extension you need:
+
+    UMN MapServer python-mapscript
+
+The extension was tested with UMN MapServer 4.0 and 4.2, 
+older versions may not work.
+
+
+
+Installation
+--------------------
+
+1. You need to build and install python-mapscript if you haven't installed yet.
+
+    Download the UMN MapServer (http://mapserver.gis.umn.edu/dload.html)
+    or use one on your system. The mapscript is included in the source package.
+
+    Unpack and compile the UMN MapServer and use the following optional
+    parameters:
+
+    proj: include projection support
+    gdal: include raster support
+    tiff: include tiff support
+
+    In some cases gdal is not necessary and mapscript can install without
+    gdal support.
+    A detailed install instruction can be found on the UMN MapServer Homepage.
+    (http://mapserver.gis.umn.edu)
+
+    Go to the directory where the UMN MapServer source code tar-ball exists:
+
+        tar -zxf mapserver-4.2.0.tar.gz
+
+    Go to the new created directory:
+
+        cd mapserver-4.2.0 
+
+    Configure an make the UMN MapServer
+
+        ./configure --with-gdal --with-proj --with-tiff
+        make
+
+    Now we can compile and install the python mapscript
+
+        cd mapscript/python/
+        python setup.py build
+
+    Some warnings are ok during the build of python mapscript
+
+    At last we either install mapscript as root:
+
+        python setup.py install
+
+    or (if you don't want to pollute your system with circumventing
+    the package installation system) you may set something
+    like this (not that the exact path depends on your system and
+    where you place the mapserver sources) for testing the stuff
+    temporarily:
+
+        export PYTHONPATH=~/mapserver-4.2.0/mapscript/python/build/lib.linux-i686-2.3
+
+2. Add the umn_mapserver extension import statements to ~/.thuban/thubanstart.py
+    if you run thuban directly from the source directory the statement is:
+
+        import Extensions.umn_mapserver.mf_import
+        import Extensions.umn_mapserver.mf_export
+        import Extensions.umn_mapserver.mf_handle
+
+    More about how to use an extension 
+    see README in thuban/Examples/simple_extensions.
+
+3. Start Thuban and use the extension.
+
+
+
+Usage
+--------------------
+
+The usage of the extension is very intuitive, so you will see what you can do
+while you are using the extension ;)

Added: packages/thuban/branches/upstream/current/Extensions/umn_mapserver/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/umn_mapserver/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/umn_mapserver/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,33 @@
+# -*- coding:latin1 -*-
+# Copyright (C) 2004 by Intevation GmbH
+# Authors:
+# Jan Schüngel <jschuengel at intevation.de> (2004)
+# Jan-Oliver Wagner <jan at intevation.de> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+# first try out whether we can import the required module
+# of UMN MapServer MapScript.
+ok = True
+try:
+    import mapscript
+except:
+    print "Problems with UMN MapServer MapScript (not installed?)"
+    ok = False
+
+if ok:
+    import mf_import
+    import mf_export
+    import mf_handle
+
+    from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+    from Thuban import _, internal_from_unicode
+
+    ext_registry.add(ExtensionDesc(
+        name = 'UMN MapServer Management',
+        version = '1.0.0',
+        authors= [ internal_from_unicode(u'Jan Sch\xfcngel') ],
+        copyright = '2004 Intevation GmbH',
+        desc = _("Provide management methods for UMN MapServer\n" \
+                 ".map-files. These can be created/imported/modified.")))

Added: packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mapfile.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mapfile.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mapfile.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1460 @@
+# -*- coding:latin1 -*-
+# Copyright (C) 2004 by Intevation GmbH
+# Authors:
+# Jan Schüngel <jschuengel at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Classes to represent '.map'-file Objects.
+
+The following Classes, which are implemented in
+mapscript are not implemented yet in this extension:
+
+ DBFInfo, errorObj, fontSetObj, graticuleObj, imageObj, itemObj,
+ labelCacheMemberObj, labelCacheObj,
+ markerCacheMembet, msTiledSHPLayerInfo, queryMapObj,
+ referenzMapObj, resultCacheMemberObj, resultCacheObj,
+ shapefileObj, shapeObj, VectorObj
+
+the following are only used to create a necessary object. They are not
+realy created as a MF_Object.
+
+ lineObj, pointObj
+"""
+
+__version__ = "$Revision: 2340 $"
+# $Source$
+# $Id: mapfile.py 2340 2004-09-03 17:00:10Z jschuengel $
+
+
+# ##################################################
+#
+# import necessary modules from python and/or thuban
+#
+# ##################################################
+
+import os
+
+from Thuban.Model.color import Color, Transparent 
+
+from Thuban.Model.classification import ClassGroupDefault, \
+                                        ClassGroupSingleton, ClassGroupRange
+
+from mapscript import layerObj, classObj, colorObj, styleObj, rectObj, symbolObj, \
+                      pointObj, lineObj
+                      
+from Thuban.Model.layer import RasterLayer
+
+# ###################################
+#
+# Definition of dictionaries
+#
+# the dictonaries are like in mapscript and are used to make it
+# easear to unterstand the key from mapscript for the settings
+#
+# ###################################
+
+shp_type = { 0:'point',
+             1:'line',
+             2:'polygon',
+             3:'raster',
+             4:'annotation',
+             5:'circle',
+             6:'query'}
+
+unit_type = { 0:"inches",
+              1:"feet",
+              2:"miles",
+              3:"meters",
+              4:"kilometers",
+              5:"dd"}
+
+legend_status_type = { 0:"OFF",
+                       1:"ON",
+                       3:"embed" } 
+                       # 2 = Default but is not allowed here
+		       
+scalebar_status_type = { 0:"OFF",
+                         1:"ON",
+                         3:"embed" } 
+                         # 2 = Default but is not allowed here
+			 
+scalebar_style_type = { 0:"0",
+                        1:"1" }
+
+scalebar_position_type = { 0:"ul",
+                           1:"lr",
+                           2:"ur",
+                           3:"ll",
+                           6:"uc",
+                           7:"lc"}
+
+layer_status_type = { 0:"OFF",
+                      1:"ON",
+                      2:"default"}
+
+legend_position_type = { 0:"ul",
+                         1:"lr",
+                         2:"ur",
+                         3:"ll",
+                         6:"uc",
+                         7:"lc"}
+
+label_size_type = { 0:"tiny",
+                    1:"small",
+                    2:"medium",
+                    3:"large",
+                    4:"giant" }
+
+#TODO: build in truetype (0:"truetype") support
+label_font_type = { 1:"bitmap" }
+
+label_position_type = { 0:"ul",
+                        1:"lr",
+                        2:"ur",
+                        3:"ll",
+                        4:"cr",
+                        5:"cl",
+                        6:"uc",
+                        7:"lc",
+                        8:"cc",
+                       10:"auto"}
+
+
+# ##################################################
+#
+# Class Definition 
+#
+# ##################################################
+
+# ##################################################
+# General Classes that are not all explicitly defined through
+# a mapfile, but rather some helper-classes.
+
+class MF_Rectangle:
+    """
+    Represents an rectanle with the bottom left
+    and top right corner.
+    """
+    def __init__(self,mf_rect):
+        self._rect = mf_rect
+    
+    def get_minx(self):
+        return self._rect.minx
+
+    def get_miny(self):
+        return self._rect.miny
+
+    def get_maxx(self):
+        return self._rect.maxx
+
+    def get_maxy(self):
+        return self._rect.maxy
+    
+    def get_rect(self):
+        return (self._rect.minx,self._rect.miny,self._rect.maxx,self._rect.maxy)
+
+    def set_rect(self, minx, miny, maxx, maxy):
+        self._rect.minx = minx
+        self._rect.miny = miny
+        self._rect.maxx = maxx
+        self._rect.maxy = maxy
+
+class MF_Color:
+    """
+    The corresponding MapScript object contains also the
+    attribute pen which defines the stroke of the feature.
+    But this actually has nothing to do with the color and
+    therefore is not support here.
+    
+    It needs to be discussed with the MapServer developers
+    whether pen would better be moved to another class.
+    
+    The hex color definition which is also supported by
+    mapscript and Thuban is not supported as it does
+    not add any capability.
+    
+    color is definied as RGB 0..255
+    """    
+    def __init__(self, mf_color):
+        self._color = mf_color
+        self._tbc_red = (float(self.get_red())/255)
+        self._tbc_green = (float(self.get_green())/255)
+        self._tbc_blue = (float(self.get_blue())/255)
+        self._thubancolor = Color(self._tbc_red,
+				  self._tbc_green,
+				  self._tbc_blue)
+
+    # TODO : Check if it is necessary to use rgb colors alone
+    # or whether it is sufficient to only use the Thuban Color.
+    # In some it is necessary as red == -1 indicates that no color
+    # is set.
+    def get_red(self):
+        return self._color.red
+
+    def get_green(self):
+        return self._color.green
+
+    def get_blue(self):
+        return self._color.blue
+        
+    def set_rgbcolor(self, red, green, blue):
+        self._color.red = red
+        self._color.green = green
+        self._color.blue = blue
+        
+        self._tbc_red = (float(self.get_red())/255)
+        self._tbc_green = (float(self.get_green())/255)
+        self._tbc_blue = (float(self.get_blue())/255)
+        self._thubancolor = Color(self._tbc_red,
+				  self._tbc_green, 
+				  self._tbc_blue)
+        
+    def get_mfcolor(self):
+        return self._color
+
+    def get_thubancolor(self):
+        return self._thubancolor     
+
+    def set_thubancolor(self, thuban_color):
+        if thuban_color != Transparent:
+            self._color.red = int(thuban_color.red * 255)
+            self._color.green = int(thuban_color.green * 255)
+            self._color.blue = int(thuban_color.blue * 255)
+            self._thubancolor = thuban_color
+
+
+class MF_Metadata:
+    """
+    Metadata is not a Object in mapscript witch can be used
+    by ease. Only the infos can get with the functions
+    "getFirstMetaDataKey", "getNextMetaDataKey" and "getMetaData".
+    To get some special Metadata you need a key. So there is a special 
+    function which create a list of the metadatakeys.
+    """
+    def __init__(self, mapobj):
+        self.mapobj = mapobj
+
+    def remove_allmetadata(self):
+        keylist = self.get_metadatakeys()
+        if keylist:
+            for key in keylist:
+                self.mapobj.removeMetaData(key)
+
+    def get_metadatakeys(self):
+        keylist = []
+        try:
+            metafkey =self.mapobj.getFirstMetaDataKey()
+            keylist.append(metafkey)
+        except:
+            return None
+        else:
+            if metafkey:
+                while metafkey:
+                    metafkey = self.mapobj.getNextMetaDataKey(metafkey)
+                    if metafkey:
+                        keylist.append(metafkey)
+                return keylist
+
+    def get_metadata(self):
+        keylist = self.get_metadatakeys()
+        metadatalist = []
+        if keylist:
+            for key in keylist:
+                metadatalist.append([key,self.mapobj.getMetaData(key)])
+            return metadatalist
+        else:
+            return None
+    
+    def get_metadatabykey(self, key):
+        return self.mapobj.getMetaData(key)
+
+    def remove_metadatabykey(self, key):
+        self.mapobj.removeMetaData(key)
+    
+    def add_metadata(self, key, data):
+        self.mapobj.setMetaData(key,data)
+
+# ################################################
+# Classes for MapServer Objects as they are
+# explicitly defined in a mapfile
+
+class MF_Outputformat:
+    """
+    The Outputformat defines which and how the image is
+    created by the mapserver.
+    
+    The following settings are used:
+    name
+    
+    The following settings are not used:
+    mimetye, driver, extension, renderer, imagemode, transparent,
+    bands, numfrotmatoptions, formatoptions, refcount, inmapfile
+    setExtension(), setMimetype(), setOption(), getOption()
+    """
+    def __init__(self, mf_outputformat):
+        self._outputformat = mf_outputformat
+    
+    def get_name(self):
+        return self._outputformat.name
+    
+
+class MF_Symbol:
+    """
+    defines a single symbol which is used in the Symbolset
+    
+    the following settings are used:
+    name, type,
+    
+    the following settings are not used:
+    sizex, sizey, points, numpoints, filled, stylelength,
+    style, imagepath, transparent, transparentcolor, character, antialias,
+    font, gap, position, linecap, linejoin, linejoinmaxsize, setPoints(),
+    getPoints(), setStyle()
+    """    
+    def __init__(self, mf_symbol = "newone"):
+        # create a circle Object like shown in Thuban
+        # because Thuban don't support other symbols
+	
+	# TODO: include the options to create a symbol, but
+	#      first implement a methode to edit Symbols in Thuban
+        if mf_symbol == "newone":
+            mf_symbol = symbolObj("")            
+            newpoint = pointObj()
+            newpoint.x = 1
+            newpoint.y = 1
+            newline = lineObj()
+            newline.add(newpoint)
+            mf_symbol.setPoints(newline)
+        
+        self._symbol = mf_symbol
+    
+    def get_symbolObj(self):
+        return self._symbol
+    
+    def get_name(self):
+        return self._symbol.name
+    
+    def set_name(self, new_name):
+        self._symbol.name = new_name
+    
+    def get_type(self):
+        return self._symbol.type
+    
+    def set_type(self, new_type):
+        # TODO include a function to set the type by a string
+        self._symbol.type = new_type
+    
+    def get_filled(self):
+        return self._symbol.filled
+    
+    def set_filled(self, new_filled):
+        if new_filled:
+            self._symbol.filled = 1
+        else:
+            self._symbol.filled = 0
+
+
+class MF_SymbolSet:
+    """
+    defines a set of symbols, may be there can only be one
+    
+    the following settings are used:
+    numsymbols,
+    appendSymbol()
+    
+    filename, imagecachesize, symbol, getSymbol(),
+    getSymbolByName(), index(), removeSymbol(),
+    save()    
+    """
+    def __init__(self, mf_symbolset):
+        self._symbolset = mf_symbolset
+        
+        # Initial Symbol List
+        self._symbols = []
+        self._i = 1
+        while self._i < self._symbolset.numsymbols:
+            self._symbols.append(MF_Symbol(self._symbolset.getSymbol(self._i)))
+            self._i += 1
+
+    def add_symbol(self, new_symbol):
+        self._symbolset.appendSymbol(new_symbol.get_symbolObj())
+        self._symbols.append(new_symbol)
+        # the save function must be run to set the symbols to the
+        # mapfile. I don't know why this ist so but it must be.
+	# the file is empty then an we can delete it
+        self._symbolset.save("tempsymbol")
+        os.remove("tempsymbol")
+
+    def get_symbol(self, symbolnr):
+        if symbolnr < self._symbolset.numsymbols:
+            return self._symbols[symbolnr-1]
+        else:
+            return None
+
+
+class MF_Class:
+    """
+    The following parameters and functions, which the mapscript style obj
+    contains, are used:
+    styles, numstyles, name, status, keyimage, layer,
+    getExpressionString(), setExpression(), getMetaData(), getFirstMetaDataKey(),
+    getNextMetaDataKey(), getStyle()
+
+    The following parameters and functions are not used:
+    label, title, template, type, minscale, maxscale, debug,
+    setExpression(), setText(), setMetaData(), drawLegendIcon(),
+    createLegendIcon(), insertStyle(), removeStyle(), moveStyleUp(),
+    moveStyleDown()
+    """
+    def __init__(self, mf_class):
+        """
+        Initialized a class from them given mapscript Class Object
+	with a list of the included styles.
+	Metadata Object will be created from the Metadata informations
+	wich are holt as a List i think.
+        """
+        self._clazz = mf_class
+        self._styles = []
+        self._numstyles = mf_class.numstyles
+        for i in range(0,self._numstyles,1):
+            self._styles.append(MF_Style(mf_class.getStyle(i)))
+        
+        if self._clazz.getExpressionString() == '"(null)"':
+            self._expression = None
+        else:
+            self._expression = self._clazz.getExpressionString()
+        
+        self.metadata = MF_Metadata(self._clazz)
+
+    def get_styles(self):
+        return self._styles
+    
+    def get_name(self):
+        return self._clazz.name
+        
+    def get_keyimage(self):
+        return self._clazz.keyimage
+        
+    def get_expressionstring(self):
+        return self._expression
+    
+    def set_name(self, newname):
+        self._clazz.name = newname
+    
+    def set_expressionstring(self, newstring):
+        self._clazz.setExpression(newstring)
+        self._expression = self._clazz.getExpressionString()
+    
+    def get_status(self):
+        if self._clazz.status == 1:
+            return True
+        else:
+            return False
+    
+    def set_status(self, new_status):
+        if new_status:
+            self._clazz.status = 1
+        else:
+            self._clazz.status = 0
+
+    def add_thubanstyle(self, tb_style, type="default"):
+        """
+        added a thuban style object to the mapobject
+        """
+        new_styleobj = MF_Style(styleObj(self._clazz))
+        if type == "line":
+            new_styleobj.set_color(tb_style.GetLineColor())
+        elif type == "point":
+            # set a default symbol to show circles not only a small dot
+            # symbol "circle" must create before
+            # TODO: create a Symbol (more see MF_SymbolSet)
+            # first the default symbol circle will be created and the size 8
+            new_styleobj.set_symbolname('circle')
+            new_styleobj.set_size(8)
+            if tb_style.GetLineColor() != Transparent:
+                new_styleobj.set_linecolor(tb_style.GetLineColor())
+            new_styleobj.set_color(tb_style.GetFill())
+        else:
+            new_styleobj.set_size(tb_style.GetLineWidth())
+            if tb_style.GetLineColor() != Transparent:
+                new_styleobj.set_linecolor(tb_style.GetLineColor())
+            new_styleobj.set_color(tb_style.GetFill())
+
+
+
+class MF_Layer:
+    """
+    The following parameters and functions, which the mapscript style obj
+    contains, are used:
+
+    classitem, numclasses, name, data, type
+    getClass(), getProjection(), getExtent(), getMetaData(),
+    getFirstMetaDataKey(), getNextMetaDataKey(), status, 
+
+
+    The following paramters and functions are not used:
+    index, map, header, footer, template, groupe, tolerance,
+    toleranceunits, symbolscale, minscale, maxscale, labelminscale
+    labelmaxscale, sizeunits, maxfeatures, offsite, transform, labelcache
+    postlabelcache, labelitem, labelsizeitem, labelangleitem, labelitemindex
+    labelsizeitemindex, labelangleitemindex, tileitem, tileindex, units
+    connection, connectiontype, numitems, filteritem, styleitem, requires
+    labelrequires, transparency, dump, debug, numprocessing, numjoins,
+    removeClass(), open(), close(), getShape(), getNumResults(), getResult()
+    getItem(), promote(), demote(), draw(), drawQuery(), queryByAttributes()
+    queryByPoint(), queryByRect(), queryByFeatures(), queryByShape(),
+    setFilter(), setFilterString(), setWKTProjection(), setProjection()
+    addFeature(), getNumFeatures(), setMetaData(), removeMetaData(),
+    getWMSFeatureInfoURL(), executeWFSGetFeature(), applySLD(), applySLDURL()
+    enerateSLD(), moveClassUp(), moveClassDown(), setProcessing(),
+    getProcessing(), clearProcessing()   
+    """
+
+    def __init__(self, mf_layer):
+        """
+	Creates the Layer Object from the mapscript Layer Object.
+	the class objects in the layer object will be stored in
+	an array. The metadata are created as a new object.
+        """
+        self._mf_layer = mf_layer
+
+        # Create Classes 
+        # there could be more then 1 
+        i = -1
+        self._classes = []
+        while i < self._mf_layer.numclasses-1:
+            i += 1
+            self._classes.append(MF_Class(self._mf_layer.getClass(i)))
+            
+        self._projection = MF_Projection(self._mf_layer.getProjection())
+        
+        # Create Metadata
+        self._metadata = MF_Metadata(self._mf_layer)
+
+    def get_index(self):
+        return self._mf_layer.index
+
+    def get_name(self):
+        return self._mf_layer.name
+    
+    def get_data(self):
+        return self._mf_layer.data
+
+    def get_classes(self):
+        return self._classes
+    
+    def set_classes(self, new_classes):
+        self._classes = new_classes
+       
+    def get_metadata(self):
+        return self._metadata
+
+    def set_metadata(self, new_metadata):
+        self._metadata = new_metadata
+    
+    def get_type(self):
+        return shp_type[self._mf_layer.type]
+
+    def get_classitem(self):
+        return self._mf_layer.classitem
+
+    def get_projection(self):
+        return self._projection
+    
+    def get_status(self):
+        # returns a integer value
+        # 0 = off, 1 = on, 2 = default(always on)
+        if self._mf_layer.status == 0:
+            return False
+        else:
+            return True
+    
+    def get_group(self):
+        return self._mf_layer.group
+
+    def set_group(self, new_group):
+        self._mf_layer.group = new_group
+    
+    def set_name(self, newname):
+        self._mf_layer.name = newname 
+    
+    def set_data(self, newdata, type="shape"):
+        if type == "raster":
+            self._mf_layer.data = newdata
+        else:
+            self._mf_layer.data = newdata[:-4]
+    
+    def set_status(self, newstatus):
+        # status can set to true or false from thuban.
+        # but mapserver supports the default value
+        self._mf_layer.status = newstatus
+    
+    def set_classitem(self, tb_field):
+        self._mf_layer.classitem = tb_field
+    
+    def set_type(self, tb_type):
+        # if type = arc its a in shapetype line
+        if tb_type == "arc":
+            self._mf_layer.type = 1
+        if tb_type == "raster":
+            self._mf_layer.type = 3
+        if shp_type.has_key(tb_type):
+            self._mf_layer.type = tb_type
+        else:
+            for shp_paar_nr in shp_type:
+               if shp_type[shp_paar_nr] == tb_type:
+                   self._mf_layer.type = shp_paar_nr
+                   return
+    
+    def set_projection(self, newprojection):
+        self._mfnewprojstring = ""
+        if newprojection:
+            self._newparams = newprojection.GetAllParameters()
+            for field in self._newparams:
+                self._mfnewprojstring = self._mfnewprojstring+ "," + field
+            self._mf_layer.setProjection(self._mfnewprojstring[1:])
+            self._projection.set_projection(newprojection)
+    
+    def add_thubanclass(self, tb_class, type=""):
+        """
+        Add a thuban class object
+        """ 
+        new_class = MF_Class(classObj(self._mf_layer))
+        self._classes.append(new_class)
+        # set the class name to the Label form thuban if given,
+        # else set it to the value
+        if tb_class.GetLabel() != "":
+            new_class.set_name(tb_class.GetLabel())
+        else:
+            if isinstance(tb_class, ClassGroupDefault):
+                new_class.set_name("default")
+            elif isinstance(tb_class, ClassGroupSingleton):
+                new_class.set_name(str(tb_class.GetValue()))
+            else:
+                new_class.set_name(None)
+        if self.get_type() == "line":
+            new_class.add_thubanstyle(tb_class.GetProperties(), type="line")
+        elif self.get_type() == "point":
+            new_class.add_thubanstyle(tb_class.GetProperties(), type="point")
+        else:
+            new_class.add_thubanstyle(tb_class.GetProperties())
+        if (type == "default"):
+            return
+        # removed the following two lines to check if the expressionstring
+        # is needed for points, because if expressionstring is a range type,
+        # no expressionstring in the default group is allowed
+        elif (tb_class.Matches("DEFAULT")):
+            return
+           # new_class.set_expressionstring('/./')
+        else:
+            #check which type of expression 
+            if isinstance(tb_class, ClassGroupRange):
+                # get the needed infos from the Range-String
+                self._range_begin = tb_class.GetRange()[0]
+                self._range_min = str(tb_class.GetMin())
+                self._range_max = str(tb_class.GetMax())
+                self._range_end = tb_class.GetRange()[len(tb_class.GetRange())-1]
+                self._range_umn = ""
+                self._range_classitem = self.get_classitem()
+                # generate the operator
+                if self._range_begin == "[":
+                    self._range_op1 = ">="
+                elif self._range_begin == "]":
+                    self._range_op1 = ">"
+                else:
+                    print "error in Thuban class properties"
+                #build op1 string for the lower limit
+                self._range_op1 = "[" + self._range_classitem + "] " + \
+                                 self._range_op1 + " " +\
+                                 self._range_min
+                # build op2 string for the upper limit
+                if self._range_end == "[":
+                    self._range_op2 = "<"
+                elif self._range_end == "]":
+                    self._range_op2 = "<="
+                else:
+                    print "error in Thuban class properties"
+
+                self._range_op2 = "[" + self._range_classitem + "] " + \
+                                 self._range_op2 + " " +\
+                                 self._range_max
+                # we only need AND here at the moment, becaus of the limits 
+                # in thuban
+                self._range_combine = "AND"
+                # check if the one limit is set to inf and then
+                # remove the second expression becaus is not needed.
+                if self._range_min == "-inf":
+                    self._range_combine = ""
+                    self._range_op1 = ""
+                elif self._range_max == "inf":
+                    self._range_combine = ""
+                    self._range_op2 = ""
+                # build the expression together
+                self._range_umn = "(" + self._range_umn + \
+                                 self._range_op1 + " " +\
+                                 self._range_combine + \
+                                 self._range_op2 + " )"
+            
+                #set the expression to the mapscript
+                new_class.set_expressionstring(self._range_umn)
+            else:
+                new_class.set_expressionstring(str(tb_class.GetValue()))
+        new_class.set_status(tb_class.IsVisible())
+
+    def remove_allclasses(self):
+        for i in range(0,len(self.get_classes()), 1):
+            self._mf_layer.removeClass(i)
+        self.set_classes([])
+
+class MF_Scalebar:
+    """
+    Represent the scalebar for a map
+
+    The following settings are used:
+    label, color, imagecolor, style, intervals, units,
+    status, position, height, width 
+    
+    The following settings are (not) used:
+    backgroundcolor,outlinecolor, postlabelcache
+    """
+    def __init__(self, mf_scalebar):
+        self._scalebar = mf_scalebar
+        self._color = MF_Color(self._scalebar.color)
+        self._imagecolor = MF_Color(self._scalebar.imagecolor)
+        self._label = MF_Label(self._scalebar.label)
+    
+    def get_label(self):
+        return self._label
+    
+    def get_color(self):
+        return self._color
+    
+    def get_imagecolor(self):
+        return self._imagecolor
+    
+    def get_style(self):
+        return self._scalebar.style
+    
+    def set_style(self, new_style):
+        self._scalebar.style = new_style
+    
+    def get_size(self):
+        #returns the size
+        return (self._scalebar.width, self._scalebar.height)
+
+    def set_size(self, new_width, new_height):
+        self._scalebar.width = new_width
+        self._scalebar.height = new_height
+    
+    def get_intervals(self):
+        return self._scalebar.intervals
+    
+    def set_intervals(self, new_intervals):
+        self._scalebar.intervals = new_intervals
+
+    def get_units(self):
+        #returns the unittype
+        return unit_type[self._scalebar.units]
+
+    def set_units(self, units):
+        if unit_type.has_key(units):
+            self._scalebar.units = units
+        else:
+            for unit_paar_nr in unit_type:
+               if unit_type[unit_paar_nr] == units:
+                   self._scalebar.units = unit_paar_nr
+        
+    def get_status(self, mode="integer"):
+        if mode == "string":
+            return scalebar_status_type[self._scalebar.status]
+        else:
+            return self._scalebar.status
+    
+    def set_status(self, new_status):
+        if scalebar_status_type.has_key(new_status):
+            self._scalebar.status = new_status
+        else:
+            for scalebar_status_type_nr in scalebar_status_type:
+                if scalebar_status_type[scalebar_status_type_nr] == new_status:
+                    self._scalebar.status = scalebar_status_type_nr
+    
+    def get_position(self, mode="integer"):
+        if mode == "string":
+            return scalebar_position_type[self._scalebar.position]
+        else:
+            return self._scalebar.position
+    
+    def set_position(self, new_position):
+        if scalebar_position_type.has_key(new_position):
+            self._scalebar.position = new_position
+        else:
+            for scalebar_position_type_nr in legend_position_type:
+                if scalebar_position_type[scalebar_position_type_nr] \
+                == new_position:
+                    self._scalebar.position = scalebar_position_type_nr
+
+
+class MF_Map:
+    """
+    The following parameters and functions, which the mapscript style obj
+    contains, are used:
+
+    name, numlayers, extent, shapepath, imagecolor, imagetype, units, getLayer,
+    status, getProjection, getMetaData, getFirstMetaDataKey, getNextMetaDataKey,
+    save(), setExtent(), height, width, setProjection(), setImageType(),
+
+    The following parameters and functions are not used:
+    maxsize, layers, symbolset, fontset, labelcache,
+    transparent, interlace, imagequality, cellsize, debug, datapattern,
+    templatepattern, configoptions
+    zoomPoint(), zoomRectangle(), zoomScale(), getLayerOrder(), setLayerOrder(),
+    clone(), removeLayer(), getLayerByName(), getSymbolByName(),
+    prepareQuery(), prepareImage(), setOutputFormat(), draw(),
+    drawQuery(), drawLegend(), drawScalebar(), embedLegend(), drawLabelCache(),
+    nextLabel(), queryByPoint(), queryByRecht(), queryByFeatures(),
+    queryByShape(), setWKTProjection(), saveQuery(), saveQueryASGML(),
+    setMetaData(), removeMetaData(), setSymbolSet(), getNumSymbols(),
+    setFontSet(), saveMapContext(), loadMapContext(), moveLayerUp(),
+    moveLayerDown(), getLayersDrawingOrder(), setLayersDrawingOrder(),
+    setConfigOption(), getConfigOption(), applyConfigOptions(), applySLD(),
+    applySLDURL(), gernerateSLD(), procecssTemplate(), processLegemdTemplate(), processQueryTemplate(),
+    getOutputFormatByName(), appendOutputFormat(), removeOutputFormat(),
+    """
+    def __init__(self, mf_map):
+        """
+	Create the map object from the mapfile mapobject which is given.
+
+	All layers in the mapfile will be written to an array.
+	"""
+        self._mf_map = mf_map
+        self._extent = MF_Rectangle(self._mf_map.extent)
+        self._imagecolor = MF_Color(self._mf_map.imagecolor)
+        self._web = MF_Web(self._mf_map.web)
+        self._legend = MF_Legend(self._mf_map.legend)
+        self._scalebar = MF_Scalebar(self._mf_map.scalebar)
+        
+        # TODO: generate the list dynamical by alle supported formats.
+        # At the moment outputformat only get by name, but in a next
+        # version there may be a function to get the outputformat by id
+        # then there is no need to define the formattypes here
+        image_types = ['gif', 'png', 'png24', 'jpeg', 'wbmp', \
+	               'swf', 'pdf', 'imagemap'] 
+        self._alloutputformats = []
+        self._imagetype = self._mf_map.imagetype
+        # create a temp imagtype, because the function getOutputFormatByName()
+        # set the imagetype to the received OutputFormat        
+        for fmtname in image_types:
+            theformat = self._mf_map.getOutputFormatByName(fmtname)
+            if theformat:
+                self._alloutputformats.append(MF_Outputformat(theformat)) 
+        self._mf_map.setImageType(self._imagetype)
+
+        self._outputformat = MF_Outputformat(self._mf_map.outputformat)
+
+        # symbols
+        self._symbolset = MF_SymbolSet(self._mf_map.symbolset)
+
+        # if the map name is not set it will return a MS string.
+        if self._mf_map.name != "MS":
+            self._name = self._mf_map.name
+        else:
+            self._name = None
+            
+        self._projection = MF_Projection(self._mf_map.getProjection())
+
+        # Initial Layer List
+        self._layers = []
+        self._i = 0
+        while self._i < self._mf_map.numlayers:
+            self._layers.append(MF_Layer(self._mf_map.getLayer(self._i)))
+            self._i += 1
+
+        # Shapepath if not set, shapepath will be empty
+        if self._mf_map.shapepath:
+            self._shapepath = self._mf_map.shapepath
+        else:
+            self._shapepath = ""
+
+        # Create Metadata
+        self._metadata = MF_Metadata(self._mf_map)
+    
+    def create_new_layer(self):
+        """
+        the new layer must create inside the mapobj, because mapscript
+        need the mapscript object as parameter for layerObj
+        """
+        new_layer = MF_Layer(layerObj(self._mf_map))
+        self._layers.append(new_layer)
+        # the new created layer must remove from the mapobject
+        # because all layer will create new in export.
+        #self._mf_map.removeLayer(self._mf_map.numlayers-1)
+        return new_layer  
+    
+    def get_mappath(self):
+        return self._mf_map.mappath
+    
+    def set_mappath(self, new_mappath):
+        self._mf_map.mappath = new_mappath
+    
+    def get_outputformat(self):
+        return self._outputformat
+    
+    def get_alloutputformats(self):
+        return self._alloutputformats
+
+    def get_imagetype(self):
+        return self._mf_map.imagetype
+    
+    def set_imagetype(self, new_imagetype):
+        self._mf_map.setImageType(new_imagetype)
+    
+    def get_symbolset(self):
+        return self._symbolset
+    
+    def get_status(self):
+        if self._mf_map.status == 1:
+            return True
+        else:
+            return False
+    
+    def set_status(self, new_status):
+        if new_status:
+            self._mf_map.status = 1
+        else:
+            self._mf_map.status = 0
+
+    def get_scalebar(self):
+        return self._scalebar
+    
+    def get_web(self):
+        return self._web
+    
+    def get_legend(self):
+        return self._legend
+    
+    def get_extent(self):
+        return self._extent
+        
+    def get_layers(self):
+        return self._layers
+    
+    def get_numlayers(self):
+        return self._mf_map.numlayers
+    
+    def get_projection(self):
+        return self._projection
+    
+    def get_name(self):
+        return self._name
+    
+    def get_shapepath(self):
+        # where are the shape files located.
+        return self._shapepath 
+    
+    def set_shapepath(self, new_shapepath):
+        # where are the shape files located..
+        self._shapepath = new_shapepath
+    
+    def get_imagetype(self):
+        return self._mf_map.imagetype
+
+    def get_layerorder(self):
+        # shows the order of layer as list
+        return self._mf_map.getLayerOrder()
+    
+    def set_layerorder(self, new_order):
+        self._mf_map.setLayerOrder(new_order)
+    
+    def get_size(self):
+        #returns the size
+        return (self._mf_map.width, self._mf_map.height)
+    
+    def get_units(self):
+        #returns the unittype
+        return unit_type[self._mf_map.units]
+    
+    def get_imagecolor(self):
+        return self._imagecolor
+    
+    def set_name(self, newname):
+        # whitespace musst be replaced, either no
+        # mapfile will be shown in the mapserver
+        if newname:
+            newname = newname.replace(" ","_")
+        self._name = newname
+        self._mf_map.name = newname
+    
+    def set_extent(self, newextent):
+        # TODO: add the shown extend here instead of the total
+        # if no size is set or if it is zero, the size will set to 1.
+        if self.get_size()[0] == - 1:
+            print "define the size first to set extent"
+            print "size is now set to (1,1)"
+            self.set_size(1,1)
+        # if an empty map is export newextent will be none
+        if newextent:
+            self._newrect = MF_Rectangle(rectObj(newextent[0],newextent[1], \
+                                    newextent[2],newextent[3]))
+            self._mf_map.setExtent(newextent[0],newextent[1], \
+                                    newextent[2],newextent[3])    
+    
+    def set_size(self, newwidth, newheight):
+        self._mf_map.width = newwidth
+        self._mf_map.height = newheight
+    
+    def set_projection(self, projection):
+        self._mfnewprojstring = ""
+        self._newparams = projection.GetAllParameters()
+        for field in self._newparams:
+            self._mfnewprojstring = self._mfnewprojstring+ "," + field
+        self._mf_map.setProjection(self._mfnewprojstring[1:])
+        self._projection.set_projection(projection)
+    
+    def set_units(self, units):
+        if unit_type.has_key(units):
+            self._mf_map.units = units
+        else:
+            for unit_paar_nr in unit_type:
+               if unit_type[unit_paar_nr] == units:
+                   self._mf_map.units = unit_paar_nr
+    
+    def get_metadata(self):
+        return self._metadata
+    
+    def add_thubanlayer(self, tb_layer):
+        """
+        Add a thuban layer
+        """
+        # this import statement placed here, because if it is placed at the
+        # beginning of this file, it produced the following error:
+        # NameError: global name 'AnnotationLayer' is not defined
+        # don't know why this error is produced and why it works
+        # if it is placed here instead of the beginning.
+        from Extensions.umn_mapserver.mf_import import AnnotationLayer
+        if hasattr(tb_layer,"extension_umn_layerobj"):
+            #print tb_layer.extension_umn_layerobj
+            #new_layer = MF_Layer(layerObj(self._mf_map))
+            new_layer = tb_layer.extension_umn_layerobj
+        else:
+            new_layer = MF_Layer(layerObj(self._mf_map))
+            self._layers.append(new_layer)
+            tb_layer.extension_umn_layerobj = new_layer
+        new_layer.remove_allclasses()
+        # init a list to set the layerorder
+        new_layer.get_index()
+        new_layer.set_name(tb_layer.Title()) 
+        # TODO: implement relative pathnames
+        # yet only absolute pathnames in the LayerObj are set 
+        if isinstance(tb_layer, RasterLayer ):
+            new_layer.set_data(tb_layer.GetImageFilename(), type="raster")
+            new_layer.set_type("raster")
+            new_layer.set_status(tb_layer.Visible())
+        elif isinstance(tb_layer, AnnotationLayer):
+            new_layer.set_type("annotation")
+            new_layer.set_status(tb_layer.Visible())
+            new_layer.set_data(tb_layer.ShapeStore().FileName())
+        else:
+            new_layer.set_data(tb_layer.ShapeStore().FileName())
+            new_layer.set_status(tb_layer.Visible())
+            new_layer.set_type(tb_layer.ShapeType())
+            if tb_layer.GetClassificationColumn():
+                new_layer.set_classitem(tb_layer.GetClassificationColumn())
+            if tb_layer.GetProjection():
+                new_layer.set_projection(tb_layer.GetProjection())
+            if tb_layer.GetClassification().GetNumGroups() > 0:
+                singletonexists = False
+                for group in range(0, \
+		                tb_layer.GetClassification().GetNumGroups(), 1):
+                    if isinstance(tb_layer.GetClassification().GetGroup(group), \
+                                    ClassGroupSingleton):
+                        singletonexists = True
+                    new_layer.add_thubanclass( \
+		                   tb_layer.GetClassification().GetGroup(group))
+                new_layer.add_thubanclass( \
+		                 tb_layer.GetClassification().GetDefaultGroup())
+                # remove the classitem if one singleton exists
+                if singletonexists == False:
+                    new_layer.set_classitem(None)
+            else:
+                new_layer.add_thubanclass( \
+		               tb_layer.GetClassification().GetDefaultGroup(), \
+		               type="default")
+        # set the projection to the layer.
+        # if the layer has its own definition use it, 
+	   # else use the main projection
+        if tb_layer.GetProjection():
+            new_layer.set_projection(tb_layer.GetProjection())
+        else:
+            new_layer.set_projection(self._projection.get_projection())
+    
+    def remove_layer(self, delnr):
+        if delnr < len(self._layers):
+            # if a layer is removed, the links for the mapscript layer and 
+            # the metadata must set new
+            # TODO: All other object in a layer obj must set a new, e.g proj.
+            for ll in range(len(self._layers)-1, delnr, -1):
+                self._layers[ll]._mf_layer = self._layers[ll-1]._mf_layer
+                self._layers[ll].set_metadata(self._layers[ll-1].get_metadata())
+               
+            self._mf_map.removeLayer(delnr)
+            self._layers.pop(delnr)
+    
+    def save_map(self, filepath):
+        # save the Map
+        # maybe an own saver can implement here
+        self._mf_map.save(filepath)
+
+
+class MF_Web:
+    """
+    Save the Web settings
+    
+    The following parametes are used:
+    imagepath, imageurl, queryformat,
+    
+    The following parameters are not used:
+    log, map, template, header, footer, empty, error, extent,
+    minscale, maxscale, mintemplate, maxtemplate
+    """
+    def __init__(self, mf_web):
+        self._mf_web = mf_web
+    
+    def get_imagepath(self):
+        return self._mf_web.imagepath
+
+    def set_imagepath(self, new_imagepath):
+        self._mf_web.imagepath = new_imagepath
+    
+    def get_imageurl(self):
+        return self._mf_web.imageurl
+    
+    def get_template(self):
+        return self._mf_web.template
+    
+    def set_template(self, new_template):
+        self._mf_web.template = new_template
+
+    def set_imageurl(self, new_imageurl):
+        self._mf_web.imageurl = new_imageurl
+    
+    def get_queryformat(self):
+        return self._mf_web.queryformat
+
+    def set_queryformat(self, new_queryformat):
+        self._mf_web.imagepath = new_queryformat
+
+
+class MF_Label:
+    """
+    The following parameters from mapscript are used:
+    type, color, size, offsetx, offsety, partials, force, buffer,
+    minfeaturesize, mindistance,
+    
+    The following parameters are not used:    
+    font, outlinecolor, shadowcolor, shadowsizex, shadowsizey, 
+    backgroundcolor, backgroundshadowcolor, backgroundshadowsizex,
+    backgroundshadowsizey, sizescaled, minsize, maxsize, position, angle,
+    autoangle, antialias, wrap, autominfeaturesize,
+    """
+    def __init__(self, mf_label):
+        """
+        Create a legend obj from the existing mapfile
+        """
+        self._label = mf_label
+        self._color = MF_Color(self._label.color)
+    
+    def get_size(self):
+        return self._label.size
+    
+    def set_size(self, new_size):
+        if label_size_type.has_key(new_size):
+            self._label.size = new_size
+        for label_size_type_nr in label_size_type:
+                if label_size_type[label_size_type_nr] == new_size:
+                    self._label.size = label_size_type_nr
+                else:
+                    self._label.size = new_size
+    
+    def get_color(self):
+        return self._color
+    
+    def get_partials(self):
+        if self._label.partials == 1:
+            return True
+        else:
+            return False
+    
+    def set_partials(self, new_partials):
+        # if partials = True
+        if new_partials:
+            self._label.partials = 1
+        elif new_partials == False:
+            self._label.partials = 0
+        else:
+            print "must be boolean"
+    
+    def get_buffer(self):
+        return self._label.buffer
+    
+    def set_buffer(self, new_buffer):
+        self._label.buffer = new_buffer
+    
+    def get_mindistance(self):
+        return self._label.mindistance
+    
+    def set_mindistance(self, new_mindistance):
+        self._label.mindistance = new_mindistance
+    
+    def get_minfeaturesize(self):
+        return self._label.minfeaturesize
+    
+    def set_minfeaturesize(self, new_minfeaturesize):
+        self._label.minfeaturesize = new_minfeaturesize
+    
+    def get_position(self, mode="integer"):
+        if mode == "string":
+            return label_position_type[self._label.position]
+        else:
+            return self._label.position
+    
+    def set_position(self, new_position):
+        if label_position_type.has_key(new_position):
+            self._label.position = new_position
+        else:
+            for label_position_type_nr in label_position_type:
+                if label_position_type[label_position_type_nr] == new_position:
+                    self._label.position = label_position_type_nr
+    
+    def get_force(self):
+        if self._label.force == 1:
+            return True
+        else:
+            return False
+    
+    def set_force(self, new_force):
+        if new_force:
+            self._label.force = 1
+        else:
+            self._label.force = 0
+    
+    def get_type(self):
+        return label_font_type[self._label.type]
+    
+    def set_type(self, new_type):
+        if label_font_type.has_key(new_type):
+            self._label.type = new_type
+        else:
+            for label_font_type_nr in label_font_type:
+                if label_font_type[label_font_type_nr] == new_type:
+                    self._label.type = label_font_type_nr
+
+    def get_offset(self):
+        return (self._label.offsetx, self._label.offsety)
+    
+    def set_offset(self, new_offsetx, new_offsety):
+        self._label.offsetx = new_offsetx
+        self._label.offsety = new_offsety
+
+
+class MF_Legend:
+    """
+    The following parameters are (not) used:
+    imagecolor, label, keysizex, keysizey, status, position,
+    
+    The following parameters are not used:
+    keyspacingx, keyspacingy,
+    outlinecolor, height, width, postlabelcache, template, map
+    """
+    def __init__(self, mf_legend):
+        """
+        Create a legend obj from the existing mapfile
+        """
+        self._mf_legend = mf_legend
+        self._imagecolor = MF_Color(self._mf_legend.imagecolor)
+        self._label = MF_Label(self._mf_legend.label)
+        
+    def get_imagecolor(self):
+        return self._imagecolor
+    
+    def get_label(self):
+        return self._label
+    
+    def get_keysize(self):
+        return (self._mf_legend.keysizex, self._mf_legend.keysizey)
+    
+    def set_keysize(self, new_keysizex, new_keysizey):
+        self._mf_legend.keysizex = new_keysizex
+        self._mf_legend.keysizey = new_keysizey
+    
+    def get_keyspacing(self):
+        return (self._mf_legend.keyspacingx, self._mf_legend.keyspacingy)
+    
+    def set_keyspacing(self, new_keyspacingx, new_keyspacingy):
+        self._mf_legend.keyspacingx = new_keyspacingx
+        self._mf_legend.keyspacingy = new_keyspacingy
+    
+    def get_status(self, mode="integer"):
+        if mode == "string":
+            return legend_status_type[self._mf_legend.status]
+        else:
+            return self._mf_legend.status
+    
+    def set_status(self, new_status):
+        if legend_status_type.has_key(new_status):
+            self._mf_legend.status = new_status
+        else:
+            for legend_status_type_nr in legend_status_type:
+                if legend_status_type[legend_status_type_nr] == new_status:
+                    self._mf_legend.status = legend_status_type_nr
+    
+    def get_position(self, mode="integer"):
+        if mode == "string":
+            return legend_position_type[self._mf_legend.position]
+        else:
+            return self._mf_legend.position
+    
+    def set_position(self, new_position):
+        if legend_position_type.has_key(new_position):
+            self._mf_legend.position = new_position
+        else:
+            for legend_position_type_nr in legend_position_type:
+                if legend_position_type[legend_position_type_nr]== new_position:
+                    self._mf_legend.position = legend_position_type_nr
+
+class MF_Projection:
+    """
+    The following parameter, which the mapscript style obj contains is used:
+
+    numargs
+    """
+    
+    def __init__(self, mf_projection):
+        """
+        Create a projection object from the given mapscript projection
+        object. If it is a epsg code the extracted from the string
+        (e.g."init=epsg:xxxx"), else the projection parameters will
+        be splitted and an array with the parameters will be creaded.
+        """
+        self._mfprojstring = mf_projection
+        self._projstring = self._mfprojstring
+        self._epsgcode = None
+        self._params = None
+        if self._mfprojstring:
+            if self._mfprojstring.find("init=epsg:") != -1:
+                self._initcode, self._epsgcode = self._mfprojstring.split(':')
+            else:  
+                self._params = []  
+                self._params = self._mfprojstring.split("+")
+                if self._params[0] == "":
+                    self._params.remove("")
+
+    def epsg_code_to_projection(self, epsg):
+        """
+        Find the projection for the given epsg code.
+    
+        Copied from Extension/wms/layer.py
+    
+        epsg -- EPSG code as string
+        """
+        #Needed only for this function
+        from Thuban.Model.resource import get_system_proj_file, EPSG_PROJ_FILE,\
+                                          EPSG_DEPRECATED_PROJ_FILE
+
+        proj_file, warnings = get_system_proj_file(EPSG_PROJ_FILE)
+
+        for proj in proj_file.GetProjections():
+            if proj.EPSGCode() == epsg:
+                return proj
+            
+        proj_file, warnings = get_system_proj_file(EPSG_DEPRECATED_PROJ_FILE)
+        for proj in proj_file.GetProjections():
+            if proj.EPSGCode() == epsg:
+                return proj
+        return None
+    
+    def get_params(self):
+        #Parameter from the mf_projectionstring as Array
+        return self._params
+        
+    def get_epsgcode(self):
+        # returnes the epsg number
+        return self._epsgcode
+        
+    def get_epsgproj(self):
+        # get an epsg projectionobject
+        return self.epsg_code_to_projection(self._epsgcode)
+    
+    def get_projection(self):
+        return self._projstring
+    
+    def set_projection(self, newprojection):
+        self._projstring = newprojection
+        self._params = newprojection.GetAllParameters()
+        self._mfnewprojstring = ""
+        for field in self._params:
+            self._mfnewprojstring = self._mfnewprojstring+ "+" + field
+        self._mfprojstring = self._mfnewprojstring
+
+
+class MF_Style:
+    """
+    The following parameters, which the mapscript style obj
+    contains, are used:
+    color, backgroundcolor, outlinecolor, size, symbolname
+
+    The following are not used:
+    symbol, sizescaled, minsize, maxsize, offsetx, offsety,
+    antialias
+    """
+ 
+    def __init__(self, mf_style):
+        """
+	Create a style object from the given mapscript style object.
+	The color Object from the color and the outlinecolor parameter
+	will be created. if the color (red, green or blue) is -1 there
+	is no definition in the mapfile and so there is no color object,
+	it will set to 'None'.
+        """
+        self._style = mf_style
+        if self._style.color.red == -1:
+            self._color = None
+        else:
+            self._color = MF_Color(self._style.color)
+        if self._style.outlinecolor.red == -1:
+            self._outlinecolor = None
+        else:
+            self._outlinecolor = MF_Color(self._style.outlinecolor)
+    
+    def get_color(self):
+        return self._color
+    
+    def get_outlinecolor(self):
+        return self._outlinecolor
+   
+    def get_size(self):
+        return self._style.size
+    
+    def set_linecolor(self, tb_color):
+        self._color = tb_color
+        new_linecolor = MF_Color(colorObj())
+        new_linecolor.set_thubancolor(tb_color)
+        self._outlinecolor = new_linecolor
+        self._style.outlinecolor = new_linecolor.get_mfcolor()
+    
+    def set_color(self, tb_color):
+        self._color = tb_color
+        new_color = MF_Color(colorObj())
+        new_color.set_thubancolor(tb_color)
+        self._color = new_color
+        self._style.color = new_color.get_mfcolor()
+    
+    def set_size(self, newsize):
+        self._style.size = newsize
+    
+    def set_symbolname(self, newsymbol):
+        # its possible to use stringnames instead of numbers
+        self._style.symbolname = newsymbol
+

Added: packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_export.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_export.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_export.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,200 @@
+# Copyright (C) 2004 by Intevation GmbH
+# -*- coding:latin1 -*-
+# Authors:
+# Jan Schüngel <jschuengel at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+This modul extend Thuban with the possibility to handle
+UMN MapServer mapfiles.
+"""
+
+__version__ = "$Revision: 2719 $"
+# $Source$
+# $Id: mf_export.py 2719 2007-01-08 16:30:29Z dpinte $
+
+
+# ###################################
+#
+# import necessary modules
+#
+# ###################################
+
+import os
+
+# mapscript
+from mapscript import mapObj
+
+# wx.Python support
+import wx
+
+# Thuban
+# use _() already now for all strings that may later be translated
+from Thuban import _
+
+# Thuban has named commands which can be registered in the central
+# instance registry.
+from Thuban.UI.command import registry, Command
+
+# needed to add the new menu
+from Thuban.UI.mainwindow import main_menu
+
+# import Map Object for the Mapfile
+from mapfile import MF_Map, MF_Symbol
+
+# ###################################
+#
+# Mainpart of the Extension
+#
+# ###################################
+
+def tbproj_to_map(tb_map, map):
+    """
+    set the projection from thuban to the mapscript
+    """
+    # TODO: epsg code support
+    # epsg will convert to parameters at the moment
+    tb_proj = tb_map.GetProjection()
+    if tb_proj:
+        map.set_projection(tb_proj)
+    
+def tblayer_to_map(tb_map, map):
+    """
+    added all layers which are displayed in thuban to the mapscript
+    if the are new, else use the associated mapobjects.
+    All other layers will be removed
+    """
+    tb_layers = tb_map.Layers()
+    oldindex = map.get_layerorder()
+    indexlist = []
+    for layer in tb_layers:
+        map.add_thubanlayer(layer)
+        layind = layer.extension_umn_layerobj.get_index()
+        indexlist.append(layind)
+    bigint = 0
+    for rmnr in oldindex:
+        if rmnr > bigint:
+            bigint = rmnr
+    removelist = []
+    for rnr in range(0, bigint+1, 1):
+        if rnr not in indexlist:
+            removelist.append(rnr)
+    
+    for i in range(len(removelist), 0, -1):
+        map.remove_layer(removelist[i-1])
+
+    map.set_layerorder(tuple(indexlist))
+
+def thuban_to_map(tb_context, map):
+    """
+    add all context from thuban to the mapscript
+    """
+    # get the thuban map
+    tb_map = tb_context.mainwindow.canvas.Map()
+    # set the title
+    map.set_name(tb_map.Title())
+    # set the projection
+    tbproj_to_map(tb_map, map)
+    # set the extent
+    tb_bbox = tb_context.mainwindow.canvas.VisibleExtent()
+    # Size must be set before, because mapscript checks it
+    # when extent is set
+    map.set_extent(tb_bbox)
+    tblayer_to_map(tb_map, map)
+
+def add_circle_symbol(map):
+    """
+    Added a circle object like the one shown in thuban
+    """
+    if map.get_symbolset().get_symbol(1):
+        return
+    else:
+        new_symbol = MF_Symbol()
+        new_symbol.set_name("circle")
+        new_symbol.set_type(2)
+        new_symbol.set_filled(True)
+        map.get_symbolset().add_symbol(new_symbol)
+
+def write_creatorcomment(path,file):
+    """
+    Added a short comment to the created map file to show
+    that the file is generated automatic
+    """
+    thuban_umn_comment = "# \n" + \
+                                "# Map file generated by Thuban (umn_mapserver Extension) \n" + \
+                                "# \n \n"
+    datafile = os.path.join(path,file)
+    
+    in_file = open(datafile,"r")
+    text_in_file = in_file.read()
+    in_file.close()
+    
+    out_file = open(datafile,"w")
+    out_file.write(thuban_umn_comment)
+    out_file.write(text_in_file) # text in Datei schreiben
+    out_file.close()    # Datei schliessen
+
+def export_mapfile(context):
+    """
+    Exports an existing mapobj and set all stuff from thuban to
+    the mapobj
+    """
+    theMap = context.mainwindow.canvas.Map().extension_umn_mapobj
+    
+    dlg = wx.FileDialog(context.mainwindow, "Save file as...", ".", "", 
+                       "UMN MapServer Mapfiles (*.map)|*.map|"     \
+                       "All files (*.*)|*.*",
+                       wx.SAVE |wx.OVERWRITE_PROMPT)
+    if dlg.ShowModal() == wx.ID_OK:
+        path = dlg.GetDirectory()
+        file = dlg.GetFilename()
+        dlg.Destroy()
+    else:
+        return
+
+    # set all thuban context to the mapobj
+    thuban_to_map(context, theMap)
+
+    #add symbol
+    add_circle_symbol(theMap)
+    
+    # shapepath vom mapfile
+    theMap.set_shapepath("")
+
+    # save the map with the integrated mapscript saver
+    theMap.save_map(os.path.join(path,file))
+    
+    # this funktion will write a commend to the generated mapfile
+    # that shows that the file is generated by thuban
+    write_creatorcomment(path,file)
+
+ 
+# check if an mapobj exists, to control the menuitem is available or not
+def _has_umn_mapobj(context):
+    """Return true if a umn_mapobj exists"""
+    return hasattr(context.mainwindow.canvas.Map(), "extension_umn_mapobj")
+ 
+# ###################################
+#
+# Hook in MapServer Extension into Thuban
+#
+# ###################################
+
+# register the new command
+registry.Add(Command("export_new_mapfile", _("Export mapfile"), \
+                     export_mapfile,  helptext = _("Create a new mapfile"), \
+                     sensitive = _has_umn_mapobj))
+
+# find the extensions menu (create it anew if not found)
+experimental_menu = main_menu.FindOrInsertMenu("experimental", \
+                                              _("Experimenta&l"))
+# find the extension menu and add a new submenu if found
+mapserver_menu = experimental_menu.FindOrInsertMenu("mapserver", \
+                                                   _("&MapServer"))
+
+# finally add the new entry to the extensions menu
+mapserver_menu.InsertItem("export_new_mapfile", after="edit_mapfile")
+
+

Added: packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_handle.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_handle.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_handle.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1408 @@
+# -*- coding:latin1 -*-
+# Copyright (C) 2004 by Intevation GmbH
+# Authors:
+# Jan Schüngel <jschuengel at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+This modul extend Thuban with the possibility to handle
+UMN MapServer mapfiles.
+"""
+
+__version__ = "$Revision: 2719 $"
+# $Source$
+# $Id: mf_handle.py 2719 2007-01-08 16:30:29Z dpinte $
+
+
+# ###################################
+#
+# import necessary modules
+#
+# ###################################
+
+import os, sys
+
+# mapscript
+from mapscript import mapObj, layerObj
+
+# wx.Python support
+import wx
+from wx import grid
+
+# Thuban
+# use _() already now for all strings that may later be translated
+from Thuban import _
+
+# Thuban has named commands which can be registered in the central
+# instance registry.
+from Thuban.UI.command import registry, Command
+
+# needed to add the new menu
+from Thuban.UI.mainwindow import main_menu
+
+# import Map Object for the Mapfile
+from mapfile import MF_Map
+
+from Thuban.UI.colordialog import ColorDialog
+
+from mapfile import unit_type, legend_status_type, legend_position_type, \
+                    label_font_type, scalebar_status_type, scalebar_style_type, \
+                    scalebar_position_type, label_position_type
+
+# ###################################
+#
+# Mainpart of the Extension
+#
+# ###################################
+
+ID_COLOR_CHANGE= 8001
+ID_IMGCOLOR_CHANGE = 8002
+
+class Map_Dialog(wx.Dialog):
+    
+    def __init__(self, parent, ID, title,
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_DIALOG_STYLE):
+                     
+        # initialize the Dialog
+        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)
+
+        # parent.canvas.Map()
+        self.tb_map = parent.canvas.Map()
+        self.tb_map_umn = self.tb_map.extension_umn_mapobj
+
+        # create name
+        box_name = wx.BoxSizer(wx.HORIZONTAL)
+        box_name.Add(wx.StaticText(self, -1, _("Map-Name:")), 0,
+                     wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        box_name.Add(wx.StaticText(self, -1, self.tb_map.Title()), 0,
+                     wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)  
+
+        #create size settings
+        insidetxt = self.tb_map_umn.get_size()
+        staticSize = wx.StaticBox(self, 1010, _("Size"), style = 0, 
+	                         name = "staticBox",   )
+        box_size = wx.StaticBoxSizer(staticSize, wx.VERTICAL)
+        
+        box_sizepartWidth = wx.BoxSizer(wx.HORIZONTAL)
+        box_sizepartWidth.Add(wx.StaticText(self, -1, _("Width: ")), 0, wx.ALL, 4)
+        self.text_width = wx.TextCtrl(self, -1, str(insidetxt[0]))
+        box_sizepartWidth.Add(self.text_width, 2, wx.ALL, 4)
+        box_size.Add(box_sizepartWidth, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
+        box_sizepartHeight = wx.BoxSizer(wx.HORIZONTAL)
+        box_sizepartHeight.Add(wx.StaticText(self, -1, _("Height: ")), 0,
+	                                    wx.ALL, 4)
+        self.text_height = wx.TextCtrl(self, -1, str(insidetxt[1]))
+        box_sizepartHeight.Add(self.text_height, 2, wx.ALL, 4)
+        box_size.Add(box_sizepartHeight, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
+        
+        #  get the web object
+        self.tb_map = parent.canvas.Map()
+        self.tb_map_umn = self.tb_map.extension_umn_mapobj
+        
+        #get the imagetype
+        umn_imagetype = self.tb_map_umn.get_imagetype()
+        # create a list with the outputformat names
+        umn_outputformats = []
+        for format in self.tb_map_umn.get_alloutputformats():
+            umn_outputformats.append(format.get_name())
+        #Imagetype selector
+        box_imagetypeStatic = wx.StaticBox(self, -1, _("Image Type"),
+                                          style = 0, name = "imagetype")
+        box_imagetype = wx.StaticBoxSizer(box_imagetypeStatic, wx.VERTICAL)
+        self.choice_imgtype = wx.Choice(self, 8060, (80, 50), 
+                                        choices = umn_outputformats)
+        EVT_CHOICE(self, 8060, self.EvtChoiceBox)
+        self.choice_imgtype.SetStringSelection(umn_imagetype)
+        box_imagetype.Add(self.choice_imgtype,0, wx.EXPAND, wx.ALL, 5)    
+        
+        #unittype
+        insideunit = self.tb_map_umn.get_units()
+        #Unittype selector
+        box_unitsStatic = wx.StaticBox(self, 1011, _("Unit Type"),
+	                              style = 0, name = "imagecolor")
+        box_units = wx.StaticBoxSizer(box_unitsStatic, wx.VERTICAL)
+        sam = []
+        for key in unit_type:
+            sam.append(unit_type[key])
+        self.choice_units = wx.Choice(self, 40, (80, 50), choices = sam)
+        self.choice_units.SetStringSelection(insideunit)
+        box_units.Add(self.choice_units,0, wx.EXPAND, wx.ALL, 5)        
+    
+        # color chouser
+        box_colorStatic = wx.StaticBox(self, 1011, _("ImageColor"),
+	                              style = 0, name = "imagecolor")
+        box_color = wx.StaticBoxSizer(box_colorStatic, wx.VERTICAL)
+        
+        # preview box
+        self.previewcolor = wx.Panel(self,99, name = 'backgroundPanel',
+	                            style = wx.SIMPLE_BORDER | wx.CLIP_CHILDREN)
+        imagecolor = self.tb_map_umn.get_imagecolor()
+        self.previewcolor.SetBackgroundColour(wx.Colour(imagecolor.get_red(),
+        imagecolor.get_green(), imagecolor.get_blue()))
+        box_color.Add(self.previewcolor, 1, wx.GROW | wx.ALL, 5)
+        # color change button, opens a new color dialog
+        button = wx.Button(self, ID_COLOR_CHANGE, _("Change Color"))
+        button.SetFocus()
+        EVT_BUTTON(self, ID_COLOR_CHANGE, self.OnChangeColor)
+        box_color.Add(button, 1, wx.EXPAND|wx.ALL, 5)
+        
+        # status
+        umn_status = self.tb_map_umn.get_status()
+        self.choice_status = wx.RadioBox(self, -1, choices=["True","False"],
+              label='status', majorDimension=1,
+              name='status check', size=wx.DefaultSize, style=wx.RA_SPECIFY_ROWS)
+        self.choice_status.SetStringSelection(str(umn_status))
+        
+        #buttons
+        box_buttons = wx.BoxSizer(wx.HORIZONTAL)
+        button = wx.Button(self, wx.ID_OK, _("OK"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        button = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        #button functions
+        EVT_BUTTON(self, wx.ID_OK, self.OnOK)
+        EVT_BUTTON(self, wx.ID_CANCEL, self.OnCancel)
+        
+        #add all boxes to the box top
+        top = wx.BoxSizer(wx.VERTICAL)
+        top.Add(box_name, 0, wx.EXPAND |wx.ALL, 5)
+        top.Add(box_size, 0, wx.EXPAND |wx.ALL, 5)
+        top.Add(box_imagetype,0, wx.EXPAND |wx.ALL, 5)
+        top.Add(box_units,0, wx.EXPAND |wx.ALL, 5)
+        top.Add(box_color,0, wx.EXPAND |wx.ALL, 5)     
+        top.Add(self.choice_status,0, wx.EXPAND |wx.ALL, 5)   
+        top.Add(box_buttons, 0, wx.ALIGN_RIGHT)
+        
+        # final layout settings
+        self.SetSizer(top)
+        top.Fit(self)
+
+    def OnChangeColor(self, event):
+        cur = self.tb_map_umn.get_imagecolor().get_thubancolor()
+        dialog = ColorDialog(self)
+        dialog.SetColor(cur)
+        self.retcolor = None
+        if dialog.ShowModal() == wx.ID_OK:
+            self.retcolor = dialog.GetColor()
+        dialog.Destroy()
+        if self.retcolor:
+            self.redcolor = int(round(self.retcolor.red*255))
+            self.greencolor = int(round(self.retcolor.green*255))
+            self.bluecolor = int(round(self.retcolor.blue*255))
+            self.previewcolor.SetBackgroundColour(wx.Colour((self.redcolor), 
+                                            int(self.greencolor), int(self.bluecolor)))
+            # refresh the colorbox to show the new color
+            self.previewcolor.Refresh()
+    
+    def EvtChoiceBox(self, event):
+        outformat = self.tb_map_umn.get_outputformat().get_name()
+
+    def RunDialog(self):
+        self.ShowModal()
+        self.Destroy()
+
+    def end_dialog(self, result):
+        self.result = result
+        if self.result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        self.tb_map_umn.set_size(int(self.text_width.GetValue()), 
+                                 int(self.text_height.GetValue()))
+        self.tb_map_umn.set_units(self.choice_units.GetStringSelection())
+        if self.choice_status.GetStringSelection() == "True":
+            self.tb_map_umn.set_status(True)
+        else:
+            self.tb_map_umn.set_status(False)
+        previewcolor = self.previewcolor.GetBackgroundColour()
+        self.tb_map_umn.get_imagecolor().set_rgbcolor(previewcolor.Red(),
+                    previewcolor.Green(), previewcolor.Blue())
+        self.tb_map_umn.set_imagetype(self.choice_imgtype.GetStringSelection())
+        self.result ="OK"
+        self.end_dialog(self.result)
+
+    def OnCancel(self, event):
+        self.end_dialog(None)
+
+
+class Web_Dialog(wx.Dialog):
+        
+    def __init__(self, parent, ID, title,
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_DIALOG_STYLE):
+                     
+        # initialize the Dialog
+        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)
+
+        #  get the web object
+        self.tb_map = parent.canvas.Map()
+        self.umn_web = self.tb_map.extension_umn_mapobj.get_web()
+    
+        # Template 
+        box_template = wx.BoxSizer(wx.HORIZONTAL)
+        box_template.Add(wx.StaticText(self, -1, _("Template:")), 0,
+                     wx.ALL|wx.ALIGN_LEFT, 4)
+        self.text_template = wx.TextCtrl(self, -1, 
+                                    str(self.umn_web.get_template()))
+        self.text_template.SetSize((250,self.text_template.GetSize()[1]))
+        box_template.Add(self.text_template, 0,
+                     wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)  
+    
+        # Imagepath 
+        box_imagepath = wx.BoxSizer(wx.HORIZONTAL)
+        box_imagepath.Add(wx.StaticText(self, -1, _("Imagepath:")), 0,
+                     wx.ALL|wx.ALIGN_LEFT, 4)
+        self.text_imagepath = wx.TextCtrl(self, -1, 
+	                                 str(self.umn_web.get_imagepath()))
+        box_imagepath.Add(self.text_imagepath, 0,
+                     wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)  
+
+        # Imageurl 
+        box_imageurl = wx.BoxSizer(wx.HORIZONTAL)
+        box_imageurl.Add(wx.StaticText(self, -1, _("Imageurl:")), 0,
+                     wx.ALL|wx.ALIGN_LEFT, 4)
+        self.text_imageurl = wx.TextCtrl(self, -1, 
+                                    str(self.umn_web.get_imageurl()))
+        box_imageurl.Add(self.text_imageurl, 0,
+                     wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)  
+        
+        #buttons
+        box_buttons = wx.BoxSizer(wx.HORIZONTAL)
+        button = wx.Button(self, wx.ID_OK, _("OK"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        button = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        #set the button funcitons
+        EVT_BUTTON(self, wx.ID_OK, self.OnOK)
+        EVT_BUTTON(self, wx.ID_CANCEL, self.OnCancel)      
+      
+        # compose the final dialog
+        top = wx.BoxSizer(wx.VERTICAL)
+        top.Add(box_template, 0, wx.EXPAND |wx.ALL, 5)
+        top.Add(box_imagepath, 0, wx.EXPAND |wx.ALL, 5)
+        top.Add(box_imageurl, 0, wx.EXPAND |wx.ALL, 5)
+        top.Add(box_buttons, 0, wx.ALIGN_RIGHT)
+        
+        # final layout settings
+        self.SetSizer(top)
+        top.Fit(self)
+
+    def RunDialog(self):
+        self.ShowModal()
+        self.Destroy()
+
+    def end_dialog(self, result):
+        self.result = result
+        if self.result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        self.umn_web.set_template(self.text_template.GetValue())
+        self.umn_web.set_imagepath(self.text_imagepath.GetValue())
+        self.umn_web.set_imageurl(self.text_imageurl.GetValue())
+        self.result ="OK"
+        self.end_dialog(self.result)
+
+    def OnCancel(self, event):
+        self.end_dialog(None)
+
+ID_METADATA_CHANGE = 8020
+
+from Extensions.umn_mapserver.mapfile import MF_Layer
+
+class Layer_Dialog(wx.Dialog):
+        
+    def __init__(self, parent, ID, title,
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_DIALOG_STYLE):
+                     
+        # initialize the Dialog
+        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)
+
+        #  get the web object
+        self.tb_layer = parent.current_layer()
+        if hasattr(self.tb_layer,"extension_umn_layerobj"):
+            self.umn_layer = self.tb_layer.extension_umn_layerobj
+        else:
+            newlayerobj = parent.canvas.Map().extension_umn_mapobj.create_new_layer()
+            self.tb_layer.extension_umn_layerobj = newlayerobj
+            self.umn_layer = self.tb_layer.extension_umn_layerobj
+        
+        # create name
+        layer_name = wx.BoxSizer(wx.HORIZONTAL)
+        layer_name.Add(wx.StaticText(self, -1, _("Layer-Name:")), 0,
+                     wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        layer_name.Add(wx.StaticText(self, -1, self.tb_layer.Title()), 0,
+                     wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)  
+ 
+        # metadata button
+        metadata_button = wx.Button(self, ID_METADATA_CHANGE, _("Edit Metadata"))
+        EVT_BUTTON(self, ID_METADATA_CHANGE, self.OnChangeMetadata)
+        
+        # Group 
+        box_group = wx.BoxSizer(wx.HORIZONTAL)
+        if self.umn_layer.get_group():
+            umn_layer_group = self.umn_layer.get_group()
+        else:
+            umn_layer_group = ""
+        box_group.Add(wx.StaticText(self, -1, _("Group:")), 0,
+                     wx.ALL|wx.ALIGN_LEFT, 4)
+        self.text_group = wx.TextCtrl(self, -1, 
+                                    str(umn_layer_group))
+        self.text_group.SetSize((250,self.text_group.GetSize()[1]))
+        box_group.Add(self.text_group, 0,
+                     wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)  
+        
+        # buttons
+        box_buttons = wx.BoxSizer(wx.HORIZONTAL)
+        button = wx.Button(self, wx.ID_OK, _("OK"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        button = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        #set the button funcitons
+        EVT_BUTTON(self, wx.ID_OK, self.OnOK)
+        EVT_BUTTON(self, wx.ID_CANCEL, self.OnCancel)      
+      
+        # compose the final dialog
+        top = wx.BoxSizer(wx.VERTICAL)
+        #top.Add(box_template, 0, wx.EXPAND |wx.ALL, 5)
+        top.Add(layer_name, 0, wx.EXPAND|wx.ALL, 5)
+        top.Add(box_group, 0, wx.EXPAND|wx.ALL, 5)
+        top.Add(metadata_button, 0, wx.EXPAND|wx.ALL, 5)
+        top.Add(box_buttons, 0, wx.ALIGN_RIGHT)
+        
+        # final layout settings
+        self.SetSizer(top)
+        top.Fit(self)
+
+    def OnChangeMetadata(self, event):
+        # set the umn_label for scalebar so the Label_Dialog can be used
+        self.umn_metadata= self.umn_layer.get_metadata()
+        dialog = Metadata_Dialog(self, -1, "Layer Metadata Settings",
+	                      size=wx.Size(450, 200),
+                 style = wx.DEFAULT_DIALOG_STYLE
+                 )
+        dialog.CenterOnScreen()
+        if dialog.ShowModal() == wx.ID_OK:
+            return
+        dialog.Destroy()
+        
+    
+    def RunDialog(self):
+        self.ShowModal()
+        self.Destroy()
+
+    def end_dialog(self, result):
+        self.result = result
+        if self.result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        if self.text_group.GetValue() == "":
+            self.umn_layer.set_group(None)
+        else:
+            self.umn_layer.set_group(self.text_group.GetValue())
+        self.result ="OK"
+        self.end_dialog(self.result)
+
+    def OnCancel(self, event):
+        self.end_dialog(None)
+
+
+ID_LABEL_CHANGE = 8011
+
+class Legend_Dialog(wx.Dialog):
+        
+    def __init__(self, parent, ID, title,
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_DIALOG_STYLE):
+                     
+        # initialize the Dialog
+        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)
+
+        #  get the web object
+        self.tb_map = parent.canvas.Map()
+        self.umn_legend = self.tb_map.extension_umn_mapobj.get_legend()
+
+        # create the Keysize
+        keySize = wx.StaticBox(self, 1010, _("KeySize"), style = 0,
+	                      name = "KeySize Box",   )
+        box_keysize = wx.StaticBoxSizer(keySize, wx.VERTICAL)
+        umn_legend_keysize = self.umn_legend.get_keysize()
+        box_sizepartWidth = wx.BoxSizer(wx.HORIZONTAL)        
+        box_sizepartWidth.Add(wx.StaticText(self, -1, _("Width: ")), 0, wx.ALL, 2)
+        self.text_keysize_width = wx.SpinCtrl(self, -1, 
+                              value=str(umn_legend_keysize[0]), max=100, min=0,
+                              name='keywidth', style=wx.SP_ARROW_KEYS)
+        box_sizepartWidth.Add(self.text_keysize_width, 2, wx.ALL, 2)
+        box_keysize.Add(box_sizepartWidth, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+        box_sizepartHeight = wx.BoxSizer(wx.HORIZONTAL)
+        box_sizepartHeight.Add(wx.StaticText(self, -1, _("Height: ")), 0, wx.ALL, 2),
+        self.text_keysize_height = wx.SpinCtrl(self, -1, 
+                              value=str(umn_legend_keysize[1]), max=100, min=0,
+                              name='keyheight', style=wx.SP_ARROW_KEYS)
+        box_sizepartHeight.Add(self.text_keysize_height, 2, wx.ALL, 2)
+        box_keysize.Add(box_sizepartHeight, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+        
+        # create the Keyspacing
+        keySpacing= wx.StaticBox(self, 1010, _("KeySpacing"), style = 0,
+	                        name = "KeySpacing Box",   )
+        box_keyspacing = wx.StaticBoxSizer(keySpacing, wx.VERTICAL)
+        umn_legend_keyspacing = self.umn_legend.get_keyspacing()
+        box_sizepartWidth = wx.BoxSizer(wx.HORIZONTAL)        
+        box_sizepartWidth.Add(wx.StaticText(self, -1, _("Width: ")), 0, wx.ALL, 2)
+        self.text_keyspacing_width = wx.SpinCtrl(self, -1, 
+                              value=str(umn_legend_keyspacing[0]), max=100,
+			      min=0, name='spacingwidth', style=wx.SP_ARROW_KEYS)
+        box_sizepartWidth.Add(self.text_keyspacing_width, 2, wx.ALL, 2)
+        box_keyspacing.Add(box_sizepartWidth, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+        box_sizepartHeight = wx.BoxSizer(wx.HORIZONTAL)
+        box_sizepartHeight.Add(wx.StaticText(self, -1, _("Height: ")), 0, wx.ALL, 2),
+        self.text_keyspacing_height = wx.SpinCtrl(self, -1, 
+                              value=str(umn_legend_keyspacing[1]), max=100,
+			      min=0,name='spacingheight', style=wx.SP_ARROW_KEYS)
+        box_sizepartHeight.Add(self.text_keyspacing_height, 2, wx.ALL, 2)
+        box_keyspacing.Add(box_sizepartHeight, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+
+        # color chooser
+        box_colorStatic = wx.StaticBox(self, 1011, _("ImageColor"),  style = 0,
+	                              name = "imagecolor")
+        box_color = wx.StaticBoxSizer(box_colorStatic, wx.VERTICAL)
+        # preview box
+        self.previewcolor = wx.Panel(self, 99, name = 'imagecolorPanel',
+	                            style = wx.SIMPLE_BORDER | wx.CLIP_CHILDREN)
+        imagecolor = self.umn_legend.get_imagecolor()
+        self.previewcolor.SetBackgroundColour(wx.Colour(imagecolor.get_red(),
+        imagecolor.get_green(), imagecolor.get_blue()))
+        box_color.Add(self.previewcolor, 1, wx.GROW | wx.ALL, 5)
+        # color change button, opens a new color dialog
+        button = wx.Button(self, ID_COLOR_CHANGE, _("Change Color"))
+        button.SetFocus()
+        EVT_BUTTON(self, ID_COLOR_CHANGE, self.OnChangeColor)
+        box_color.Add(button, 1, wx.EXPAND|wx.ALL, 5)
+
+        # status
+        umn_legend_status= self.umn_legend.get_status(mode="string")
+        possible_choices = []
+        for key in legend_status_type:
+            possible_choices.append(legend_status_type[key])
+        self.choice_status = wx.RadioBox(self, -1, choices=possible_choices,
+              label='Status', majorDimension=1,
+              name='status check', size=wx.DefaultSize, style=wx.RA_SPECIFY_ROWS)
+        self.choice_status.SetStringSelection(umn_legend_status)
+
+        # create the positionbox
+        umn_legend_position= self.umn_legend.get_position(mode="string")
+        possible_choices = []
+        for key in legend_position_type:
+            possible_choices.append(legend_position_type[key])
+        self.choice_position = wx.RadioBox(self, -1, choices=possible_choices,
+                                          label='Position', majorDimension=1,
+                                          name='position check', 
+					  size=wx.DefaultSize,
+					  style=wx.RA_SPECIFY_ROWS)
+        self.choice_position.SetStringSelection(umn_legend_position)
+        
+        # button for label
+        labelbutton = wx.Button(self, ID_LABEL_CHANGE, _("Change Label"))
+        EVT_BUTTON(self, ID_LABEL_CHANGE, self.OnChangeLabel)
+        
+        #buttons
+        box_buttons = wx.BoxSizer(wx.HORIZONTAL)
+        button = wx.Button(self, wx.ID_OK, _("OK"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        button = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        #set the button funcitons
+        EVT_BUTTON(self, wx.ID_OK, self.OnOK)
+        EVT_BUTTON(self, wx.ID_CANCEL, self.OnCancel)        
+        
+        # compose the final layout
+        top = wx.BoxSizer(wx.VERTICAL)
+        top.Add(box_keysize,0, wx.EXPAND |wx.ALL, 5) 
+        top.Add(box_keyspacing,0, wx.EXPAND |wx.ALL, 5) 
+        top.Add(box_color,0, wx.EXPAND |wx.ALL, 5) 
+        top.Add(self.choice_status,0, wx.EXPAND |wx.ALL, 5) 
+        top.Add(self.choice_position,0, wx.EXPAND |wx.ALL, 5) 
+        top.Add(labelbutton, 1, wx.EXPAND|wx.ALL, 5)
+        top.Add(box_buttons, 0, wx.ALIGN_RIGHT)
+        
+        # final layout settings
+        self.SetSizer(top)
+        top.Fit(self)
+    
+    def OnChangeLabel(self, event):
+        self.umn_label = self.umn_legend.get_label()
+        dialog = Label_Dialog(self, -1, "Legend Label Settings",
+	                      size=wx.Size(350, 200),
+                 style = wx.DEFAULT_DIALOG_STYLE
+                 )
+        dialog.CenterOnScreen()
+        if dialog.ShowModal() == wx.ID_OK:
+            return
+        dialog.Destroy()
+    
+    def OnChangeColor(self, event):
+        cur = self.umn_legend.get_imagecolor().get_thubancolor()
+        dialog = ColorDialog(self)
+        dialog.SetColor(cur)
+        self.retcolor = None
+        if dialog.ShowModal() == wx.ID_OK:
+            self.retcolor = dialog.GetColor()
+        dialog.Destroy()
+        if self.retcolor:
+            self.redcolor = int(round(self.retcolor.red*255))
+            self.greencolor = int(round(self.retcolor.green*255))
+            self.bluecolor = int(round(self.retcolor.blue*255))
+            self.previewcolor.SetBackgroundColour(wx.Colour(int(self.redcolor), 
+                                                           int(self.greencolor),
+					                   int(self.bluecolor)))
+            # refresh the colorbox to show the new color
+            self.previewcolor.Refresh()
+
+    def RunDialog(self):
+        self.ShowModal()
+        self.Destroy()
+
+    def end_dialog(self, result):
+        self.result = result
+        if self.result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        self.umn_legend.set_keysize(self.text_keysize_width.GetValue(),
+                                    self.text_keysize_height.GetValue())
+        self.umn_legend.set_keyspacing(self.text_keyspacing_width.GetValue(),
+                                    self.text_keyspacing_height.GetValue())
+        self.umn_legend.set_status(self.choice_status.GetStringSelection())
+        self.umn_legend.set_position(self.choice_position.GetStringSelection())
+        previewcolor = self.previewcolor.GetBackgroundColour()
+        self.umn_legend.get_imagecolor().set_rgbcolor(previewcolor.Red(),
+                    previewcolor.Green(), previewcolor.Blue())
+        self.result ="OK"
+        self.end_dialog(self.result)
+
+    def OnCancel(self, event):
+        self.end_dialog(None)
+
+class Label_Dialog(wx.Dialog):
+    
+    def __init__(self, parent, ID, title,
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_DIALOG_STYLE):
+                     
+        # initialize the Dialog
+        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)
+
+        #  get the web object
+        self.umn_label = parent.umn_label
+
+        # size
+        labelsize= wx.StaticBox(self, 1010, _("Size"), style = 0,
+	                       name = "Size Box",   )
+        box_labelsize = wx.StaticBoxSizer(labelsize, wx.VERTICAL)
+        umn_label_size= self.umn_label.get_size()
+        box_size = wx.BoxSizer(wx.HORIZONTAL)        
+        self.text_labelsize = wx.SpinCtrl(self, -1, 
+                              value=str(umn_label_size), max=10, min=0,
+                              name='size', style=wx.SP_ARROW_KEYS)
+        box_size.Add(self.text_labelsize, 2, wx.ALL, 2)
+        box_labelsize.Add(box_size, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+
+        # color chooser
+        box_colorStatic = wx.StaticBox(self, 1011, _("Color"),  style = 0,
+	                              name = "color")
+        box_color = wx.StaticBoxSizer(box_colorStatic, wx.VERTICAL)
+        # preview box
+        self.previewcolor = wx.Panel(self, 99, name = 'colorPanel',
+	                            style = wx.SIMPLE_BORDER | wx.CLIP_CHILDREN)
+        color = self.umn_label.get_color()
+        self.previewcolor.SetBackgroundColour(wx.Colour(color.get_red(),
+        color.get_green(), color.get_blue()))
+        box_color.Add(self.previewcolor, 1, wx.GROW | wx.ALL, 5)
+        # color change button, opens a new color dialog
+        button = wx.Button(self, ID_COLOR_CHANGE, _("Change Color"))
+        button.SetFocus()
+        EVT_BUTTON(self, ID_COLOR_CHANGE, self.OnChangeColor)
+        box_color.Add(button, 1, wx.EXPAND|wx.ALL, 5)
+
+        #get the set type
+        insidetype = self.umn_label.get_type()
+        #create the type selector for fonttype (Bitmap, TrueType)
+        # TODO: Truetype is not supported yet
+        box_typeStatic = wx.StaticBox(self, 1011, _("Type"),  style = 0,
+	                             name = "type")
+        box_type = wx.StaticBoxSizer(box_typeStatic, wx.VERTICAL)
+        sam = []
+        for key in label_font_type:
+            # dont add truetype
+            #if key != 0:
+            sam.append(label_font_type[key])
+        self.choice_type = wx.Choice(self, 40, (80, 50), choices = sam)
+        self.choice_type.SetStringSelection(insidetype)
+        box_type.Add(self.choice_type,0, wx.EXPAND, wx.ALL, 5)        
+
+        # Offset
+        offset= wx.StaticBox(self, 1010, _("Offset"), style = 0,
+	                    name = "Offset Box",   )
+        box_offset = wx.StaticBoxSizer(offset, wx.VERTICAL)
+        umn_label_offset = self.umn_label.get_offset()
+        box_offsetX = wx.BoxSizer(wx.HORIZONTAL)        
+        box_offsetX.Add(wx.StaticText(self, -1, _("X: ")), 0, wx.ALL, 2)
+        self.text_offsetx = wx.SpinCtrl(self, -1, 
+                              value=str(umn_label_offset[0]), max=20, min=0,
+                              name='offsetX', style=wx.SP_ARROW_KEYS)
+        box_offsetX.Add(self.text_offsetx, 2, wx.ALL, 2)
+        box_offset.Add(box_offsetX, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+        box_offsetY = wx.BoxSizer(wx.HORIZONTAL)
+        box_offsetY.Add(wx.StaticText(self, -1, _("Y: ")), 0, wx.ALL, 2),
+        self.text_offsety = wx.SpinCtrl(self, -1, 
+                              value=str(umn_label_offset[1]), max=100, min=0,
+                              name='offsetY', style=wx.SP_ARROW_KEYS)
+        box_offsetY.Add(self.text_offsety, 2, wx.ALL, 2)
+        box_offset.Add(box_offsetY, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+        
+        # partials
+        umn_partials = self.umn_label.get_partials()
+        self.choice_partials = wx.RadioBox(self, -1, choices=["True","False"],
+                                          label='partials', majorDimension=1,
+                                          name='partials check', 
+					  size=wx.DefaultSize,
+	                                  style=wx.RA_SPECIFY_ROWS)
+        self.choice_partials.SetStringSelection(str(umn_partials))
+
+        # force
+        umn_force = self.umn_label.get_force()
+        self.choice_force = wx.RadioBox(self, -1, choices=["True","False"],
+              label='force', majorDimension=1,
+              name='force check', size=wx.DefaultSize, style=wx.RA_SPECIFY_ROWS)
+        self.choice_force.SetStringSelection(str(umn_force))
+
+        # buffer
+        buffer = wx.StaticBox(self, 1010, _("Buffer"), style = 0,
+	                     name = "Buffer Box",   )
+        box_buffer = wx.StaticBoxSizer(buffer, wx.VERTICAL)
+        umn_buffer= self.umn_label.get_buffer()
+        box_buffertext = wx.BoxSizer(wx.HORIZONTAL)        
+        self.text_buffer = wx.SpinCtrl(self, -1, 
+                              value=str(umn_buffer), max=10, min=0,
+                              name='size', style=wx.SP_ARROW_KEYS)
+        box_buffertext.Add(self.text_buffer, 2, wx.ALL, 2)
+        box_buffer.Add(box_buffertext, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+
+        # minfeaturesize
+        minfeaturesize = wx.StaticBox(self, 1010, _("Minfeaturesize"),
+	                             style = 0, name = "Minfeaturesize Box")
+        box_minfeaturesize = wx.StaticBoxSizer(minfeaturesize, wx.VERTICAL)
+        umn_minfeaturesize= self.umn_label.get_minfeaturesize()
+        box_minfeaturesizetext = wx.BoxSizer(wx.HORIZONTAL)        
+        self.text_minfeaturesize = wx.SpinCtrl(self, -1, 
+                              value=str(umn_minfeaturesize), max=10, min=-1,
+                              name='minfeaturesize', style=wx.SP_ARROW_KEYS)
+        box_minfeaturesizetext.Add(self.text_minfeaturesize, 2, wx.ALL, 2)
+        box_minfeaturesize.Add(box_minfeaturesizetext, 0, 
+                                             wx.ALIGN_RIGHT | wx.ALL, 2)
+
+        # mindistance
+        mindistance = wx.StaticBox(self, 1010, _("Mindistance"), style = 0,
+                                            name = "Mindistance Box",   )
+        box_mindistance = wx.StaticBoxSizer(mindistance, wx.VERTICAL)
+        umn_mindistance= self.umn_label.get_mindistance()
+        box_mindistancetext = wx.BoxSizer(wx.HORIZONTAL)        
+        self.text_mindistance = wx.SpinCtrl(self, -1, 
+                              value=str(umn_mindistance), max=10, min=-1,
+                              name='mindistance', style=wx.SP_ARROW_KEYS)
+        box_mindistancetext.Add(self.text_mindistance, 2, wx.ALL, 2)
+        box_mindistance.Add(box_mindistancetext, 0, 
+                                             wx.ALIGN_RIGHT | wx.ALL, 2)
+        
+        # position
+        umn_label_position= self.umn_label.get_position(mode="string")
+        possible_choices = []
+        for key in label_position_type:
+            possible_choices.append(label_position_type[key])
+        self.choice_position = wx.RadioBox(self, -1, choices=possible_choices,
+                                          label='Position', majorDimension=1,
+                                          name='position check', 
+					  size=wx.DefaultSize,
+	                                  style=wx.RA_SPECIFY_ROWS)
+        self.choice_position.SetStringSelection(umn_label_position)
+  
+        #buttons
+        box_buttons = wx.BoxSizer(wx.HORIZONTAL)
+        button = wx.Button(self, wx.ID_OK, _("OK"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        button = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        #set the button funcitons
+        EVT_BUTTON(self, wx.ID_OK, self.OnOK)
+        EVT_BUTTON(self, wx.ID_CANCEL, self.OnCancel)        
+        
+        # compose the Dialog
+        top = wx.BoxSizer(wx.VERTICAL)
+        
+        top1 = wx.BoxSizer(wx.HORIZONTAL)
+        top1.Add(box_labelsize,0, wx.EXPAND |wx.ALL, 5) 
+        top1.Add(box_color,0, wx.EXPAND |wx.ALL, 5) 
+        top1.Add(box_minfeaturesize,0, wx.EXPAND |wx.ALL, 5) 
+        
+        top2 = wx.BoxSizer(wx.HORIZONTAL)
+        top2.Add(box_type,0,wx.EXPAND |wx.ALL, 5)
+        top2.Add(box_offset,0, wx.EXPAND |wx.ALL, 5)   
+        top2.Add(box_mindistance,0, wx.EXPAND |wx.ALL, 5) 
+        
+        top3 = wx.BoxSizer(wx.HORIZONTAL)
+        top3.Add(self.choice_partials,0, wx.EXPAND |wx.ALL, 5) 
+        top3.Add(box_buffer,0, wx.EXPAND |wx.ALL, 5) 
+        top3.Add(self.choice_force,0, wx.EXPAND |wx.ALL, 5) 
+        
+        top.Add(top1, 0, wx.EXPAND)
+        top.Add(top2, 0, wx.EXPAND)
+        top.Add(top3, 0, wx.EXPAND)
+        top.Add(self.choice_position,0, wx.EXPAND |wx.ALL, 5) 
+        top.Add(box_buttons, 0, wx.ALIGN_RIGHT)
+
+        # final layout settings
+        self.SetSizer(top)
+        top.Fit(self)
+    
+    def OnChangeColor(self, event):
+        cur = self.umn_label.get_color().get_thubancolor()
+        dialog = ColorDialog(self)
+        dialog.SetColor(cur)
+        self.retcolor = None
+        if dialog.ShowModal() == wx.ID_OK:
+            self.retcolor = dialog.GetColor()
+        dialog.Destroy()
+        if self.retcolor:
+            self.redcolor = int(round(self.retcolor.red*255))
+            self.greencolor = int(round(self.retcolor.green*255))
+            self.bluecolor = int(round(self.retcolor.blue*255))
+            self.previewcolor.SetBackgroundColour(wx.Colour(int(self.redcolor), 
+                                                           int(self.greencolor),
+					                   int(self.bluecolor)))
+            # refresh the colorbox to show the new color
+            self.previewcolor.Refresh()
+
+    def RunDialog(self):
+        self.ShowModal()
+        self.Destroy()
+
+    def end_dialog(self, result):
+        self.result = result
+        if self.result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        self.umn_label.set_size(self.text_labelsize.GetValue())
+        self.umn_label.set_offset(self.text_offsetx.GetValue(),
+	                          self.text_offsety.GetValue())
+        self.umn_label.set_type(self.choice_type.GetStringSelection())
+        if self.choice_partials.GetStringSelection() == "True":
+            self.umn_label.set_partials(True)
+        else:
+            self.umn_label.set_partials(False)
+        previewcolor = self.previewcolor.GetBackgroundColour()
+        self.umn_label.get_color().set_rgbcolor(previewcolor.Red(),
+                    previewcolor.Green(), previewcolor.Blue())
+        self.umn_label.set_mindistance(self.text_mindistance.GetValue())
+        self.umn_label.set_minfeaturesize(self.text_minfeaturesize.GetValue())
+        self.umn_label.set_position(self.choice_position.GetStringSelection())
+        self.umn_label.set_buffer(self.text_buffer.GetValue())
+        if self.choice_force.GetStringSelection() == "True":
+            self.umn_label.set_force(True)
+        else:
+            self.umn_label.set_force(False)
+        self.result ="OK"
+        self.end_dialog(self.result)
+
+    def OnCancel(self, event):
+        self.end_dialog(None)
+    
+class Scalebar_Dialog(wx.Dialog):
+    
+    def __init__(self, parent, ID, title,
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_DIALOG_STYLE):
+                     
+        # initialize the Dialog
+        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)
+
+        #  get the web object
+        self.tb_map = parent.canvas.Map()
+        self.umn_scalebar = self.tb_map.extension_umn_mapobj.get_scalebar()
+
+        # color chooser
+        box_colorStatic = wx.StaticBox(self, 1011, _("Color"),  style = 0,
+	                              name = "color")
+        box_color = wx.StaticBoxSizer(box_colorStatic, wx.VERTICAL)
+        # preview box
+        self.previewcolor = wx.Panel(self, 99, name = 'colorPanel',
+	                            style = wx.SIMPLE_BORDER | wx.CLIP_CHILDREN)
+        color = self.umn_scalebar.get_color()
+        self.previewcolor.SetBackgroundColour(wx.Colour(color.get_red(),
+        color.get_green(), color.get_blue()))
+        box_color.Add(self.previewcolor, 1, wx.GROW | wx.ALL, 5)
+        # color change button, opens a new color dialog
+        button = wx.Button(self, ID_COLOR_CHANGE, _("Change Color"))
+        button.SetFocus()
+        EVT_BUTTON(self, ID_COLOR_CHANGE, self.OnChangeColor)
+        box_color.Add(button, 1, wx.EXPAND|wx.ALL, 5)
+        # show the two color chooser horizontal
+        colorHor = wx.BoxSizer(wx.HORIZONTAL)
+        colorHor.Add(box_color,0, wx.EXPAND |wx.ALL, 5) 
+        
+        # imagecolor chooser
+        box_imgcolorStatic = wx.StaticBox(self, 1011, _("Image Color"), 
+	                                 style = 0, name = "imgcolor")
+        box_imgcolor = wx.StaticBoxSizer(box_imgcolorStatic, wx.VERTICAL)
+        # preview box
+        self.previewimgcolor = wx.Panel(self, 99, name = 'colorPanel',
+	                               style = wx.SIMPLE_BORDER|wx.CLIP_CHILDREN)
+        color = self.umn_scalebar.get_imagecolor()
+        self.previewimgcolor.SetBackgroundColour(wx.Colour(color.get_red(),
+                              color.get_green(), color.get_blue()))
+        box_imgcolor.Add(self.previewimgcolor, 1, wx.GROW | wx.ALL, 5)
+        # color change button, opens a new color dialog
+        button = wx.Button(self, ID_IMGCOLOR_CHANGE, _("Change ImageColor"))
+        button.SetFocus()
+        EVT_BUTTON(self, ID_IMGCOLOR_CHANGE, self.OnChangeImageColor)
+        box_imgcolor.Add(button, 1, wx.EXPAND|wx.ALL, 5)
+        colorHor.Add(box_imgcolor,0, wx.EXPAND |wx.ALL, 5)
+        
+        # create the intervals
+        intervalsStatic = wx.StaticBox(self, 1010, _("Intervals"), style = 0,
+	                              name = "Intervals Box",   )
+        box_intervals = wx.StaticBoxSizer(intervalsStatic, wx.VERTICAL)
+        umn_scalebar_intervals = self.umn_scalebar.get_intervals()
+        self.text_intervals = wx.SpinCtrl(self, -1, 
+                              value=str(umn_scalebar_intervals), max=100, min=0,
+                              name='intervals', style=wx.SP_ARROW_KEYS)
+        box_intervals.Add(self.text_intervals, 0, wx.ALIGN_RIGHT | wx.ALL, 2)
+        hori2 = wx.BoxSizer(wx.HORIZONTAL)
+        hori2.Add(box_intervals,0, wx.EXPAND |wx.ALL, 5)
+
+        #style
+        umn_scalebar_style= self.umn_scalebar.get_style()
+        possible_choices = []
+        for key in scalebar_style_type:
+            possible_choices.append(scalebar_style_type[key])
+        self.choice_style = wx.RadioBox(self, -1, choices=possible_choices,
+              label='Style', majorDimension=1,
+              name='style check', size=wx.DefaultSize, style=wx.RA_SPECIFY_ROWS)
+        self.choice_style.SetSelection(umn_scalebar_style)
+        hori2.Add(self.choice_style, 1, wx.EXPAND|wx.ALL, 5)
+        
+        #create size settings
+        try:
+            insidetxt = self.umn_scalebar.get_size()
+        except:
+            insidetxt = (0,0)
+        # create the Size Box
+        staticSize = wx.StaticBox(self, -1, _("Size"), style = 0, 
+	                         name="sizeBox")
+        box_size = wx.StaticBoxSizer(staticSize, wx.HORIZONTAL)
+        
+        box_sizepartWidth = wx.BoxSizer(wx.HORIZONTAL)
+        box_sizepartWidth.Add(wx.StaticText(self, -1, _("Width: ")), 0, wx.ALL, 4)
+        self.text_width = wx.TextCtrl(self, -1, str(insidetxt[0]))
+        box_sizepartWidth.Add(self.text_width, 2, wx.ALL, 4)
+        box_size.Add(box_sizepartWidth, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
+        box_sizepartHeight = wx.BoxSizer(wx.HORIZONTAL)
+        box_sizepartHeight.Add(wx.StaticText(self, -1, _("Height: ")), 0,
+	                                    wx.ALL, 4)
+        self.text_height = wx.TextCtrl(self, -1, str(insidetxt[1]))
+        box_sizepartHeight.Add(self.text_height, 2, wx.ALL, 4)
+        box_size.Add(box_sizepartHeight, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
+        
+        # status
+        umn_scalebar_status= self.umn_scalebar.get_status(mode="string")
+        possible_choices = []
+        for key in legend_status_type:
+            possible_choices.append(scalebar_status_type[key])
+        self.choice_status = wx.RadioBox(self, -1, choices=possible_choices,
+              label='Status', majorDimension=1,
+              name='status check', size=wx.DefaultSize, style=wx.RA_SPECIFY_ROWS)
+        self.choice_status.SetStringSelection(umn_scalebar_status)
+        
+        # position
+        umn_scalebar_position= self.umn_scalebar.get_position(mode="string")
+        possible_choices = []
+        for key in scalebar_position_type:
+            possible_choices.append(scalebar_position_type[key])
+        self.choice_position = wx.RadioBox(self, -1, choices=possible_choices,
+                                      label='Position', majorDimension=1,
+                                      name='position check', size=wx.DefaultSize,
+	                              style=wx.RA_SPECIFY_ROWS)
+        self.choice_position.SetStringSelection(umn_scalebar_position)
+        
+        #get the set unittype
+        insideunit = self.umn_scalebar .get_units()
+        #create the Unittype selector
+        box_unitsStatic = wx.StaticBox(self, -1, _("Unit Type"),  style = 0,
+	                              name = "unittype")
+        box_units = wx.StaticBoxSizer(box_unitsStatic, wx.VERTICAL)
+        sam = []
+        for key in unit_type:
+            sam.append(unit_type[key])
+        self.choice_units = wx.Choice(self, 40, (80, 50), choices = sam)
+        self.choice_units.SetStringSelection(insideunit)
+        box_units.Add(self.choice_units,0, wx.EXPAND, wx.ALL, 5)    
+        
+        # button for label
+        labelbutton = wx.Button(self, ID_LABEL_CHANGE, _("Change Label"))
+        EVT_BUTTON(self, ID_LABEL_CHANGE, self.OnChangeLabel)
+        
+        #buttons
+        box_buttons = wx.BoxSizer(wx.HORIZONTAL)
+        button = wx.Button(self, wx.ID_OK, _("OK"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        button = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        button.SetFocus()
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        #set the button funcitons
+        EVT_BUTTON(self, wx.ID_OK, self.OnOK)
+        EVT_BUTTON(self, wx.ID_CANCEL, self.OnCancel)      
+      
+        # compose the dialog
+        top = wx.BoxSizer(wx.VERTICAL)
+        top.Add(colorHor,0, wx.EXPAND |wx.ALL, 5)
+        top.Add(hori2, 1, wx.EXPAND|wx.ALL, 5)
+        top.Add(box_size, 1, wx.EXPAND|wx.ALL, 5)
+        top.Add(self.choice_status,0, wx.EXPAND |wx.ALL, 5) 
+        top.Add(self.choice_position,0, wx.EXPAND |wx.ALL, 5) 
+        top.Add(box_units, 1, wx.EXPAND|wx.ALL, 5)
+        top.Add(labelbutton, 0, wx.EXPAND|wx.ALL, 5)
+        top.Add(box_buttons, 0, wx.ALIGN_RIGHT)
+        
+        # final layout settings
+        self.SetSizer(top)
+        top.Fit(self)
+    
+    def OnChangeLabel(self, event):
+        # set the umn_label for scalebar so the Label_Dialog can be used
+        self.umn_label = self.umn_scalebar.get_label()
+        dialog = Label_Dialog(self, -1, "Scalbar Label Settings",
+	                      size=wx.Size(350, 200),
+                 style = wx.DEFAULT_DIALOG_STYLE
+                 )
+        dialog.CenterOnScreen()
+        if dialog.ShowModal() == wx.ID_OK:
+            return
+        dialog.Destroy()
+
+    def OnChangeImageColor(self, event):
+        cur = self.umn_scalebar.get_imagecolor().get_thubancolor()
+        dialog = ColorDialog(self)
+        dialog.SetColor(cur)
+        self.retcolor = None
+        if dialog.ShowModal() == wx.ID_OK:
+            self.retcolor = dialog.GetColor()
+        dialog.Destroy()
+        if self.retcolor:
+            self.redcolor = int(round(self.retcolor.red*255))
+            self.greencolor = int(round(self.retcolor.green*255))
+            self.bluecolor = int(round(self.retcolor.blue*255))
+            self.previewimgcolor.SetBackgroundColour(wx.Colour(int(self.redcolor), 
+                                                           int(self.greencolor),
+							   int(self.bluecolor)))
+            # refresh the colorbox to show the new color
+            self.previewimgcolor.Refresh()
+
+    def OnChangeColor(self, event):
+        cur = self.umn_scalebar.get_color().get_thubancolor()
+        dialog = ColorDialog(self)
+        dialog.SetColor(cur)
+        self.retcolor = None
+        if dialog.ShowModal() == wx.ID_OK:
+            self.retcolor = dialog.GetColor()
+        dialog.Destroy()
+        if self.retcolor:
+            self.redcolor = int(round(self.retcolor.red*255))
+            self.greencolor = int(round(self.retcolor.green*255))
+            self.bluecolor = int(round(self.retcolor.blue*255))
+            self.previewcolor.SetBackgroundColour(wx.Colour(int(self.redcolor), 
+                                                           int(self.greencolor),
+					                   int(self.bluecolor)))
+            # refresh the colorbox to show the new color
+            self.previewcolor.Refresh()
+
+    def RunDialog(self):
+        self.ShowModal()
+        self.Destroy()
+
+    def end_dialog(self, result):
+        self.result = result
+        if self.result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        self.umn_scalebar.set_status(self.choice_status.GetStringSelection())
+        self.umn_scalebar.set_units(self.choice_units.GetStringSelection())
+        self.umn_scalebar.set_intervals(self.text_intervals.GetValue())
+        self.umn_scalebar.set_style(self.choice_style.GetSelection())
+        self.umn_scalebar.set_position(self.choice_position.GetStringSelection())
+        self.umn_scalebar.set_size(int(self.text_width.GetValue()), 
+	                           int(self.text_height.GetValue()))
+
+        previewcolor = self.previewcolor.GetBackgroundColour()
+        self.umn_scalebar.get_color().set_rgbcolor(previewcolor.Red(),
+                    previewcolor.Green(), previewcolor.Blue())
+        previewimgcolor = self.previewimgcolor.GetBackgroundColour()
+        self.umn_scalebar.get_imagecolor().set_rgbcolor(previewimgcolor.Red(),
+                    previewimgcolor.Green(), previewimgcolor.Blue())
+        self.result ="OK"
+        self.end_dialog(self.result)
+
+    def OnCancel(self, event):
+        self.end_dialog(None)
+
+
+class Metadata_CustomDataTable(grid.PyGridTableBase):
+    """
+    creates a custum Grid.
+    
+    copied from the wx. demo.
+    """
+    def __init__(self, data):
+        gridPyGridTableBase.__init__(self)
+
+        self.colLabels = ['ID', 'Description']
+        self.dataTypes = [wx.GRID_VALUE_STRING,
+                          wx.GRID_VALUE_STRING
+                          ]
+        
+        if data:
+            self.data = data
+        else:
+            self.data = [["",""]]    #--------------------------------------------------
+    # required methods for the grid.PyGridTableBase interface
+
+    def GetNumberRows(self):
+        return len(self.data) + 1
+
+    def GetNumberCols(self):
+        return len(self.data[0])
+
+    def IsEmptyCell(self, row, col):
+        try:
+            return not self.data[row][col]
+        except IndexError:
+            return true
+
+    # Get/Set values in the table.  The Python version of these
+    # methods can handle any data-type, (as long as the Editor and
+    # Renderer understands the type too,) not just strings as in the
+    # C++ version.
+    def GetValue(self, row, col):
+        try:
+            return self.data[row][col]
+        except IndexError:
+            return ''
+
+    def SetValue(self, row, col, value):
+        try:
+            self.data[row][col] = value
+        except IndexError:
+            # add a new row
+            
+            self.data.append([''] * self.GetNumberCols())
+            self.SetValue(row, col, value)
+
+            # tell the grid we've added a row
+            msg = grid.GridTableMessage(self,                             # The table
+                                     wx.GRIDTABLE_NOTIFY_ROWS_APPENDED, # what we did to it
+                                     1)                                # how many
+
+            self.GetView().ProcessTableMessage(msg)
+
+    #--------------------------------------------------
+    # Some optional methods
+
+    # Called when the grid needs to display labels
+    def GetColLabelValue(self, col):
+        return self.colLabels[col]
+
+    # Called to determine the kind of editor/renderer to use by
+    # default, doesn't necessarily have to be the same type used
+    # natively by the editor/renderer if they know how to convert.
+    def GetTypeName(self, row, col):
+        return self.dataTypes[col]
+
+    # Called to determine how the data can be fetched and stored by the
+    # editor and renderer.  This allows you to enforce some type-safety
+    # in the grid.
+    def CanGetValueAs(self, row, col, typeName):
+        colType = self.dataTypes[col].split(':')[0]
+        if typeName == colType:
+            return true
+        else:
+            return False
+
+    def CanSetValueAs(self, row, col, typeName):
+        return self.CanGetValueAs(row, col, typeName)
+
+
+class Metadata_TableGrid(grid.Grid):
+    def __init__(self, parent, data):
+        grid.Grid.__init__(self, parent, -1)
+
+        self.table = Metadata_CustomDataTable(data)
+
+        # The second parameter means that the grid is to take ownership of the
+        # table and will destroy it when done.  Otherwise you would need to keep
+        # a reference to it and call it's Destroy method later.
+        self.SetTable(self.table, true)
+
+        self.SetRowLabelSize(0)
+        self.SetColMinimalWidth(0,180)
+        self.SetColSize(0,180)
+        self.SetColMinimalWidth(1,250)
+        self.SetColSize(1,250)
+        self.SetMargins(0,0)
+        EVT_GRID_CELL_LEFT_DCLICK(self, self.OnLeftDClick)
+
+    def get_table(self):
+        return self.table
+
+    # I do this because I don't like the default behaviour of not starting the
+    # cell editor on double clicks, but only a second click.
+    def OnLeftDClick(self, evt):
+        if self.CanEnableCellControl():
+            self.EnableCellEditControl()
+
+
+class Metadata_Dialog(wx.Dialog):
+    
+    def __init__(self, parent, ID, title,
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_DIALOG_STYLE):
+                     
+        # initialize the Dialog
+        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)
+        
+        #  get the web object
+        if hasattr(parent,"umn_metadata"):
+            self.umn_metadata = parent.umn_metadata
+        else:
+            self.tb_map = parent.canvas.Map()
+            self.umn_metadata = self.tb_map.extension_umn_mapobj.get_metadata()
+        
+        
+        # at all items to the dataset
+        self.grid = Metadata_TableGrid(self, self.umn_metadata.get_metadata())
+        
+        #buttons
+        box_buttons = wx.BoxSizer(wx.HORIZONTAL)
+        button = wx.Button(self, wx.ID_OK, _("OK"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        button = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        button.SetFocus()
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        #set the button funcitons
+        EVT_BUTTON(self, wx.ID_OK, self.OnOK)
+        EVT_BUTTON(self, wx.ID_CANCEL, self.OnCancel)      
+        
+        # compose the dialog
+        top = wx.BoxSizer(wx.VERTICAL)
+        top.Add(self.grid, 1, wx.GROW|wx.ALL, 5)
+        top.Add(box_buttons, 0, wx.ALIGN_RIGHT)
+        
+        # final layout settings
+        self.SetSizer(top)
+        #top.Fit(self)
+        
+    def OnItemActivated(self, event):
+        self.currentItem = event.m_itemIndex
+
+    def OnDoubleClick(self, event):
+        print "OnDoubleClick" +self.list.GetItemText(self.currentItem)
+        event.Skip()
+        
+    def OnSize(self, event):
+        w,h = self.GetClientSizeTuple()
+        self.list.SetDimensions(0, 0, w, h)
+        
+    def RunDialog(self):
+        self.ShowModal()
+        self.Destroy()
+
+    def end_dialog(self, result):
+        self.result = result
+        if self.result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        # added all metadatas to the mapobj,
+        # first remove the old ones
+        self.umn_metadata.remove_allmetadata()
+        for x in range(self.grid.get_table().GetNumberRows()-2,-1, -1):
+            if self.grid.get_table().GetValue(x,0):
+                self.umn_metadata.add_metadata(str(self.grid.get_table().GetValue(x,0)),\
+                     str(self.grid.get_table().GetValue(x,1)))
+
+        self.result ="OK"
+        self.end_dialog(self.result)
+
+    def OnCancel(self, event):
+        self.end_dialog(None)
+        
+        
+        
+
+def metadatasettings(context):
+    win = Metadata_Dialog(context.mainwindow, -1, "Metadata Settings",
+                          size=wx.Size(450, 250),
+                          style = wx.DEFAULT_DIALOG_STYLE)
+    win.CenterOnScreen()
+    val = win.ShowModal()    
+    
+
+def scalebarsettings(context):
+    win = Scalebar_Dialog(context.mainwindow, -1, "Scalebar Settings",
+                          size=wx.Size(350, 200),
+                          style = wx.DEFAULT_DIALOG_STYLE)
+    win.CenterOnScreen()
+    val = win.ShowModal()
+
+def mapsettings(context):
+    win = Map_Dialog(context.mainwindow, -1, "Map Settings",
+                     size=wx.Size(350, 200),
+                     style = wx.DEFAULT_DIALOG_STYLE)
+    win.CenterOnScreen()
+    val = win.ShowModal()
+
+def outputformatsettings(context):
+    win = OutputFormat_Dialog(context.mainwindow, -1, "OutputFormat Settings", 
+                              size=wx.Size(350, 200),
+		              style = wx.DEFAULT_DIALOG_STYLE)
+    win.CenterOnScreen()
+    val = win.ShowModal()
+
+def websettings(context):
+    win = Web_Dialog(context.mainwindow, -1, "Web Settings",
+                     size=wx.Size(350, 200),
+                     style = wx.DEFAULT_DIALOG_STYLE)
+    win.CenterOnScreen()
+    val = win.ShowModal()
+
+def layersettings(context):
+    win = Layer_Dialog(context.mainwindow, -1, "Layer Settings",
+                     size=wx.Size(350, 200),
+                     style = wx.DEFAULT_DIALOG_STYLE)
+    win.CenterOnScreen()
+    val = win.ShowModal()
+
+def legendsettings(context):
+    win = Legend_Dialog(context.mainwindow, -1, "Legend Settings",
+                        size=wx.Size(350, 200),
+                        style = wx.DEFAULT_DIALOG_STYLE)
+    win.CenterOnScreen()
+    val = win.ShowModal()
+
+# TODO: Maybe can be imported from another class
+# check if an mapobj exists, to control the menuitem is available or not
+def _has_umn_mapobj(context):
+    """Return true if a umn_mapobj exists"""
+    return hasattr(context.mainwindow.canvas.Map(), "extension_umn_mapobj")
+
+def _has_umn_mapobj_and_selectedlayer(context):
+    """Return true if a umn_mapobj exists"""
+    # temporary disabled
+    #return False
+    if context.mainwindow.has_selected_layer():
+        return hasattr(context.mainwindow.canvas.Map(), "extension_umn_mapobj")
+    else:
+        return False
+
+# ###################################
+#
+# Hook in MapServer Extension into Thuban
+#
+# ###################################
+
+# find the extensions menu (create it anew if not found)
+experimental_menu = main_menu.FindOrInsertMenu("experimental",
+                                             _("Experimenta&l"))
+# find the extension menu and add a new submenu if found
+mapserver_menu = experimental_menu.FindOrInsertMenu("mapserver",
+                                                  _("&MapServer"))
+
+# find the MapServer menu and add a new submenu if found
+mapserver_edit_menu = mapserver_menu.FindOrInsertMenu("edit_mapfile",
+                                                  _("&Edit mapfile"), \
+                                                  after = "import_layer_from_mapfile")
+
+# register the new command (Map Settings Dialog)
+registry.Add(Command("Map Settings", _("Map"), mapsettings,
+                     helptext = _("Edit the Map Setting"), \
+                     sensitive = _has_umn_mapobj))
+# finally add the new entry to the extensions menu
+mapserver_edit_menu.InsertItem("Map Settings")
+
+
+# register the new command (Map Settings Dialog)
+registry.Add(Command("Web Settings", _("Web"),
+                     websettings,
+                     helptext = _("Edit the Web Setting"), \
+                     sensitive = _has_umn_mapobj))
+# finally add the new entry to the extensions menu
+mapserver_edit_menu.InsertItem("Web Settings")
+
+# register the new command (Layer Settings Dialog)
+registry.Add(Command("Layer Settings", _("Layer"),
+                     layersettings,
+                     helptext = _("Edit the Layer Setting of the aktive Layer"), \
+                     sensitive = _has_umn_mapobj_and_selectedlayer))
+# finally add the new entry to the extensions menu
+mapserver_edit_menu.InsertItem("Layer Settings")
+
+# register the new command (Legend Settings Dialog)
+registry.Add(Command("Legend Settings", _("Legend"),
+                     legendsettings,
+                     helptext = _("Edit the Legend Setting"), \
+                     sensitive = _has_umn_mapobj))
+# finally add the new entry to the extensions menu
+mapserver_edit_menu.InsertItem("Legend Settings")
+
+# register the new command (Scalebar Settings Dialog)
+registry.Add(Command("Scalebar Settings", _("Scalebar"),
+                     scalebarsettings,
+                     helptext = _("Edit the Scalebar Setting"), \
+                     sensitive = _has_umn_mapobj))
+# finally add the new entry to the extensions menu
+mapserver_edit_menu.InsertItem("Scalebar Settings")
+
+# register the new command (Scalebar Settings Dialog)
+registry.Add(Command("Metadata Settings", _("Metadata"),
+                     metadatasettings,
+                     helptext = _("Edit the Metadata Setting"), \
+                     sensitive = _has_umn_mapobj))
+# finally add the new entry to the extensions menu
+mapserver_edit_menu.InsertItem("Metadata Settings")
+
+

Added: packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_import.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_import.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/umn_mapserver/mf_import.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,762 @@
+# -*- coding:latin1 -*-
+# Copyright (C) 2004 by Intevation GmbH
+# Authors:
+# Jan Schüngel <jschuengel at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+This module extends Thuban with the possibility to handle
+UMN MapServer mapfiles.
+"""
+
+__version__ = "$Revision: 2719 $"
+# $Source$
+# $Id: mf_import.py 2719 2007-01-08 16:30:29Z dpinte $
+
+
+
+# ###################################
+#
+# import necessary modules
+#
+# ###################################
+
+import os, re
+
+from mapscript import mapObj
+
+import wx
+
+# use _() already now for all strings that may later be translated
+from Thuban import _
+
+# Thuban has named commands which can be registered in the central
+# instance registry.
+from Thuban.UI.command import registry, Command
+
+# The instance of the main menu of the Thuban application
+from Thuban.UI import mainwindow
+
+# The layer an projection from Thuban
+from Thuban.Model.layer import Layer, RasterLayer
+from Thuban.Model.proj import Projection
+
+# needed to add the new menu
+from Thuban.UI.mainwindow import main_menu
+
+from Thuban.Model.classification import ClassGroupSingleton, \
+                                        ClassGroupRange, \
+                                        ClassGroupProperties, \
+                                        ClassGroupDefault
+
+from Thuban.Model.range import Range
+
+# The Thuban color objects
+from Thuban.Model.color import Transparent 
+
+# import Map Object for the Mapfile
+from mapfile import MF_Map
+
+# ###################################
+#
+# Mainpart of the Extension
+#
+# ###################################
+from Thuban.Model.layer import BaseLayer
+class AnnotationLayer(BaseLayer):
+    """
+    Class to show AnnontationLayer in Thuban.
+    This Class is temporary and has only the task 
+    to indicate the layer in the layerlist.
+    """
+    def __init__(self, title, data, visible = False, projection = None):
+        
+        BaseLayer.__init__(self, title, 
+                                 visible = visible,
+                                 projection = projection)
+        self.store = None
+        self.SetShapeStore(data)
+    
+    def SetShapeStore(self, store):
+        self.store = store
+    
+    def ShapeStore(self):
+        return self.store
+    
+    def ShapeType(self):
+        """Return the type of the shapes in the layer.
+        """
+        return "annotation"
+    
+    def BoundingBox(self):
+        """Return the layer's bounding box in the intrinsic coordinate system.
+
+        If the layer has no shapes, return None.
+        """
+        return self.store.BoundingBox()
+
+    def LatLongBoundingBox(self):
+        """Return the layer's bounding box in lat/long coordinates.
+
+        Return None, if the layer doesn't contain any shapes.
+        """
+        bbox = self.BoundingBox()
+        if bbox is not None and self.projection is not None:
+            bbox = self.projection.InverseBBox(bbox)
+        return bbox
+
+
+def set_projection_to_tb(tb_con, mapobj):
+    """
+    Helpfunction to set the projection in thuban.
+    
+    Parameters:
+        tb_con -- The thuban conext (mapobj or layerobj)
+        mapobj -- The mapobject (from mapscript)
+    """
+    if (mapobj.get_projection().get_params() != None):
+        projparams = mapobj.get_projection().get_params()
+        # check if it is an latlong projection, becaues one
+        # more parameter is needed in that case
+        addtometer = False
+        for param in projparams:
+            projkey = param.split("=")
+            if projkey[0] == "proj":
+                if projkey[1] == "latlong":
+                    addtometer = True
+            if projkey[0] == "to_meter":
+                addtometer = False
+        if addtometer == True:
+            projparams.append("to_meter=0.017453")
+        tb_con.SetProjection(Projection(projparams))
+    if mapobj.get_projection().get_epsgcode() != None:
+        projepsg = mapobj.get_projection().get_epsgproj()
+        tb_con.SetProjection(projepsg)  
+
+def create_rangeexpression(mapexprstr):
+    """
+    create a expressionstring in thuban style from an given
+    mapfile expressionstring 
+    
+    mapexprstr = the expressionstring from the mapfile
+    """
+    attribut_expr = "\[\w+\]"
+    attribut = re.compile(attribut_expr)
+    operator_expr = ">=|<=|<|>|="
+    operator = re.compile(operator_expr)
+    #only and now supported
+    link_expr = "AND" 
+    link = re.compile(link_expr)
+    oneexpr = "\s*\[\w+\]\s*>*<*=*\s*\w+"
+    theexpr = re.compile(oneexpr)
+    
+    # init the string variables to build the string later
+    thestring = ""
+    strbegin = None
+    strmin = None
+    strmax = None
+    strend = None
+
+    link_result = link.findall(mapexprstr)
+    attr = attribut.findall(mapexprstr)
+    if len(link_result) == 0 and len(attr) == 1:
+        strattr = attr[0][1:-1]
+        expression = theexpr.findall(mapexprstr)
+        if expression:
+            operator_result = operator.search(mapexprstr)
+            if operator_result.group(0) == ">=":
+                strbegin =  "["
+                strmin = operator_result.string[operator_result.start()+2:].replace(" ","")
+                strmax = "oo"
+                strend = "]"
+            elif operator_result.group(0) == "<=":
+                strbegin =  "["
+                strmin = "-oo"
+                strmax = operator_result.string[operator_result.start()+2:].replace(" ","")
+                strend = "]"
+            elif operator_result.group(0) == ">":
+                strbegin = "]"
+                strmin = operator_result.string[operator_result.start()+1:].replace(" ","")
+                strmax = "oo"
+                strend = "]"
+            elif operator_result.group(0) == "<":
+                strbegin = "["
+                strmin = "-oo"
+                strmax = operator_result.string[operator_result.start()+1:].replace(" ","")
+                strend = "["
+            elif operator_result.group(0) == "=":
+                # create a singleton, not implemented yet
+                errorstring = "singleton creation not implemented yet"
+            else:
+                errorstring = "no operator found"
+        else:
+            errorstring = "no expression found"
+    elif len(link_result) == 1:
+        if attr[0] == attr[1]:
+            strattr = attr[0][1:-1]
+            first_expr,second_expr = mapexprstr.split("AND")
+            oneexpr_result = theexpr.findall(mapexprstr)
+            operator1_result = operator.search(first_expr)
+            operator2_result = operator.search(second_expr)
+            errorstring = "operators are wrong"
+            if operator1_result.group(0)[0] == "<" and \
+               operator2_result.group(0)[0] == ">":
+                optemt = operator1_result
+                operator1_result = operator2_result
+                operator2_result = optemt
+            if operator1_result.group(0) == ">=":
+                strbegin =  "["
+                strmin = operator1_result.string[operator1_result.start()+2:].replace(" ","")
+            elif operator1_result.group(0) == ">":
+                strbegin = "]"
+                strmin = operator1_result.string[operator1_result.start()+1:].replace(" ","")
+            if operator2_result.group(0) == "<=":
+                strend =  "]"
+                strmax = operator2_result.string[operator2_result.start()+2:].replace(" ","")
+            elif operator2_result.group(0) == "<" and operator1_result != ">" :
+                strend = "["
+                strmax = operator2_result.string[operator2_result.start()+1:].replace(" ","")
+            if strmax < strmin:
+                errorstring = "values are wrong"
+                strbegin = None
+        else:
+           errorstring = "Attributes not equal"
+    elif len(link_result) == 0:
+        errorstring = "Link expression not supported"
+    else:
+        errorstring = "More then two expressions"
+
+    #create the expression thestring
+    if strbegin and strmin and strmax and strend:
+        thestring = strbegin +strmin+";"+strmax + strend
+        return (strattr, thestring)
+    else:
+        return (None,errorstring)
+
+def add_annotationlayer(context, tb_map, mapobj, maplayer):
+    """
+    add a polygonlayer to thuban
+    
+    tb_map = context.mainwindow.canvas.Map()
+    
+    mapobj = the Mapobject created from the mapfile
+    
+    maplayer = layer obj to add to thuban
+    """
+    filepath = mapobj.get_mappath()
+    layertitle = maplayer.get_name()
+    if maplayer.get_data():
+        if os.path.isabs(maplayer.get_data()):
+            filename = maplayer.get_data() +".shp"
+        else:
+            filename = os.path.join(filepath, mapobj.get_shapepath(), \
+                                           maplayer.get_data())
+            filename = filename + ".shp"
+        # Normalize the pathname by collapses 
+        # redundant separators and up-level references
+        filename = os.path.normpath(filename)
+    else:
+        context.mainwindow.RunMessageBox(_('Error Loading Layer'),
+            _("no shp file definied, maybe used a feature obj '%s'.") % layertitle)
+    # try to open the layer
+    try:
+        store = context.application.Session().OpenShapefile(filename)
+    except IOError:
+        # the layer couldn't be opened
+        context.mainwindow.RunMessageBox(_('Open Shapepath'),
+                                         _("Can't open the file '%s'.") % filename)
+    else:
+        # added an annotation layer as empty layer to thuban
+        # because thuban don't supports annotation.
+        layertitle = maplayer.get_name()
+        annotationlayer = AnnotationLayer(layertitle,store)
+        # associate a copy of the maplayer object to the layer in thuban.
+        annotationlayer.extension_umn_layerobj = maplayer
+        tb_map.AddLayer(annotationlayer)
+    
+
+def add_rasterlayer(context, tb_map, mapobj, maplayer):
+    """
+    add a rasterlayer to thuban
+    
+    tb_map = context.mainwindow.canvas.Map()
+    
+    mapobj = the Mapobject created from the mapfile
+    
+    maplayer = layer obj to add to thuban
+    """
+    imgpath = maplayer.get_data()
+    shapepath = mapobj.get_shapepath()
+    filepath = mapobj.get_mappath()
+    layertitle = maplayer.get_name()
+    # if there is no imagepath defined, the Raster Layer could not load
+    if imgpath == None:
+        context.mainwindow.RunMessageBox(_('Error Loading Raster Layer'),
+                                         _("Can't open the rasterlayer '%s'.") % layertitle)
+    else:
+        if os.path.isabs(imgpath):
+            filename = imgpath
+        else:
+            filename = os.path.join(filepath, shapepath,imgpath) 
+        # Normalize the pathname by collapses 
+        # redundant separators and up-level references
+        filename = os.path.normpath(filename)
+        rasterlayer = RasterLayer(layertitle, filename)
+        # set the visible status
+        rasterlayer.SetVisible(maplayer.get_status())
+        #add the projection if exists
+        set_projection_to_tb(rasterlayer, maplayer)
+        
+        # associate a copy of the maplayer object to the layer in thuban.
+        rasterlayer.extension_umn_layerobj = maplayer
+        tb_map.AddLayer(rasterlayer)
+
+
+def add_polygonlayer(context, tb_map, mapobj, maplayer):
+    """
+    add a polygonlayer to thuban
+    
+    tb_map = context.mainwindow.canvas.Map()
+    
+    mapobj = the Mapobject created from the mapfile
+    
+    maplayer = layer obj to add to thuban
+    """
+    filepath = mapobj.get_mappath()
+    layertitle = maplayer.get_name()
+    if maplayer.get_data():
+        if os.path.isabs(maplayer.get_data()):
+            filename = maplayer.get_data() +".shp"
+        else:
+            filename = os.path.join(filepath, mapobj.get_shapepath(), \
+                                           maplayer.get_data())
+            filename = filename + ".shp"
+        # Normalize the pathname by collapses 
+        # redundant separators and up-level references
+        filename = os.path.normpath(filename)
+    else:
+        context.mainwindow.RunMessageBox(_('Error Loading Layer'),
+            _("no shp file definied, maybe used a feature obj '%s'.") % layertitle)
+    # try to open the layer
+    try:
+        store = context.application.Session().OpenShapefile(filename)
+    except IOError:
+        # the layer couldn't be opened
+        context.mainwindow.RunMessageBox(_('Open Shapepath'),
+                                         _("Can't open the file '%s'.") % filename)
+    else:
+        # create a new layer which will be added to thuban later
+        layer = Layer(layertitle, store)
+        # all classes of the maplayer
+        map_clazzes = maplayer.get_classes()
+        # number of layers loaded vom maplayer
+        map_numclazzes = len(map_clazzes)
+        # defaultclazzset is necessary to know if a default class is set
+        # in thuban. if is not and there are more them one class in the
+        # mapfile the colors of the default layer in thuban musst 
+        # set to Transparence
+        defaultclazzset = None
+
+        # create a class in thuban for every class in the maplayer
+        for map_clazznr in range(0, map_numclazzes, 1):
+            # define the color
+            map_clazz = map_clazzes[map_clazznr]
+            layer_style = map_clazz.get_styles()[0]
+            clazz_name = map_clazz.get_name()
+            clazz = layer.GetClassification()
+            prop = ClassGroupProperties()
+            # set the layerprojection if given
+            # TODO check this, becaus it is not working correctly
+            # set_projection_to_tb(layer, maplayer)
+
+            # if outline color is defined use it else set transparent
+            if layer_style.get_outlinecolor():
+               tb_color = layer_style.get_outlinecolor().get_thubancolor()
+               prop.SetLineColor(tb_color)
+            else:
+                prop.SetLineColor(Transparent)
+            # if color is defined use it as fillcolor
+            # but if the layer type is line use the color as linecolor
+            if layer_style.get_color():
+                tb_color = layer_style.get_color().get_thubancolor()
+                if maplayer.get_type() == 'line':
+                    prop.SetLineColor(tb_color)
+                else:
+                    prop.SetFill(tb_color)
+            else:
+                prop.SetFill(Transparent)
+
+            #set size for the line
+            if ((maplayer.get_type() == 'polygon') or   
+                 (maplayer.get_type() == 'line')):
+                if layer_style.get_size():
+                    prop.SetLineWidth(layer_style.get_size())
+                    
+            # generate special expression classes to show in thuban
+            # not all possibilities from the MapServer are supported now
+            # supporteed:
+            #    String comparisons
+            # not supported:
+            #    Regular expressions
+            #    Logical expressions
+            expressionstring = map_clazz.get_expressionstring()
+            if (((map_numclazzes == 1) & (not expressionstring)) or
+               ((map_numclazzes > 1) & (expressionstring == None)) or
+               (expressionstring == '/./')):
+                if clazz_name == None:
+                    clazz_name = ""
+                new_group = ClassGroupDefault(props = prop, label = clazz_name)
+                new_group.SetVisible(map_clazz.get_status())
+                clazz.SetDefaultGroup(new_group)
+                defaultclazzset = True
+                # break, because alle classes behind the one which definies the
+                # default will be ignored by mapserver. See sample
+                # TODO: if possible set it as invisible class in thuban, but
+                #       show the parts of that class as default.
+                #       not possible at the moment ?
+                break
+                
+            # this is the String comparison.
+            # the expressionstring is enclosed by the ' or " indications
+            elif ((expressionstring[0] == "'") or
+                 (expressionstring[0] == '"')):
+                expressionclassitem = maplayer.get_classitem().upper()
+                layer.SetClassificationColumn(expressionclassitem)
+                try:
+                    theexpression = int(expressionstring[1:-1])
+                except:
+                    theexpression = expressionstring[1:-1]
+                if clazz_name == None:
+                    clazz_name = str("")
+                new_group = ClassGroupSingleton(value = theexpression,
+                                                props = prop,
+                                                label = clazz_name)
+                new_group.SetVisible(map_clazz.get_status())
+                clazz.AppendGroup(new_group)
+            elif (expressionstring[0] == "("): 
+                expressionclassitem, thubanexpr \
+                              = create_rangeexpression(expressionstring[1:-1])
+                if expressionclassitem == None:
+                    if clazz_name == None:
+                        clazz_showtxt = "Nr. " + str(map_clazznr+1)
+                    else:
+                        clazz_showtxt = clazz_name
+                    context.mainwindow.RunMessageBox(_('Error Loading Expression'), \
+                            _("%s \n" + \
+                               "Can't load the Expression from layer \n" + \
+                               "Layer: %s ; Class: %s\n" + \
+                               "Expression: %s")\
+                            %(thubanexpr, layer.title, clazz_showtxt, expressionstring[1:-1]) )
+                else:
+                    layer.SetClassificationColumn(expressionclassitem)
+                    if clazz_name == None:
+                        clazz_name = str("")
+                    expressionrange = Range(thubanexpr)
+                    new_group = ClassGroupRange(expressionrange,
+                                                props = prop,
+                                                label = clazz_name)
+                    new_group.SetVisible(map_clazz.get_status())
+                    clazz.AppendGroup(new_group)
+
+            else:
+                new_group = ClassGroupSingleton(props = prop,label = clazz_name)
+                new_group.SetVisible(map_clazz.get_status())
+                clazz.AppendGroup(new_group)
+        
+        # if there is no default layer set,
+        # the color and linecolor will set as Transparent.
+        if (not defaultclazzset):
+            proptp = ClassGroupProperties()
+            proptp.SetLineColor(Transparent)
+            new_group = ClassGroupDefault(props = proptp)
+            clazz.SetDefaultGroup(new_group)
+            defaultclazzset = None
+        
+        # set the visible status
+        layer.SetVisible(maplayer.get_status())
+        #add the projection if exists
+        set_projection_to_tb(layer, maplayer)
+        
+        # associate a copy of the maplayer object to the layer in thuban.
+        layer.extension_umn_layerobj =maplayer
+        #add the layer into thuban
+        tb_map.AddLayer(layer)
+
+
+def select_layer2import(context, mapobj):
+    """
+    shows a dialog to select the layers to import.
+    
+    mapobj = the Mapobject created from the mapfile
+    """
+    # Show number of Layer found in file
+    numlayers = len(mapobj.get_layers())
+    if numlayers == 0:
+        context.mainwindow.RunMessageBox(_('Loading Layer'),
+                                     _("No Layer found."))
+    else:
+        context.mainwindow.RunMessageBox(_('Loading Layer'),
+                                         _("%s Layer loaded from file.") % numlayers)
+    # Show a dialog to select layers to load into thuban only    
+    lst = []
+    selectedlayer = []
+    numlayers = len(mapobj.get_layers())
+    for layernr in range(0, numlayers,1):
+        lst.append(mapobj.get_layers()[layernr].get_name() +
+                  " (" + mapobj.get_layers()[layernr].get_type() +")" )
+            
+    dlgsize = (300,130+len(lst)*20)
+    if dlgsize[1] >= 300:
+        dlgsize = (300,300)
+    dlg = wx.MultipleChoiceDialog(context.mainwindow,
+                                 "Select the layers from the\n" +
+                                 "list to load into thuban.\n" +
+                                 "annotation not supported !",
+                                 "Select Layer.", lst, size = dlgsize)
+    if (dlg.ShowModal() == wx.ID_OK):
+        selectedlayer = dlg.GetValue()
+    return selectedlayer
+
+def import_layer_from_mapfile(context):
+    """
+    Import only the layers which are selectes from a mapfile
+    """
+    # open a dialog to select the mapfile to import
+    dlg = wx.FileDialog(context.mainwindow,
+                       _("Select MapFile file"), ".", "",
+                       _("UMN MapServer Mapfiles (*.map)|*.map|") +
+                       _("All Files (*.*)|*.*"),
+                       wx.OPEN|wx.OVERWRITE_PROMPT)
+    if dlg.ShowModal() == wx.ID_OK:
+        filename = dlg.GetPath()
+        dlg.Destroy()
+    else:
+        return
+
+    # Parse mapfile
+    mapobj = parse_mapfile(filename)
+       
+    # Show number of Layer found in file
+    numlayers = len(mapobj.get_layers())
+    if numlayers == 0:
+        context.mainwindow.RunMessageBox(_('Loading Layer'),
+                                     _("No Layer found."))
+    else:
+        context.mainwindow.RunMessageBox(_('Loading Layer'),
+                                         _("%s Layer loaded from file.") % numlayers)
+    # Show a dialog to select layers to load into thuban only
+    # if the mapfile contains any layer
+    if numlayers != 0:
+        selectedlayer = select_layer2import(context,mapobj)
+    else:
+        selectedlayer = []
+
+def import_layer_from_mapfile(context):
+    """
+    import layers from a mapfile
+    """
+    # open a dialog to select the mapfile to import from
+    dlg = wx.FileDialog(context.mainwindow,
+                       _("Select MapFile file"), ".", "",
+                       _("UMN MapServer Mapfiles (*.map)|*.map|") +
+                       _("All Files (*.*)|*.*"),
+                       wx.OPEN|wx.OVERWRITE_PROMPT)
+    if dlg.ShowModal() == wx.ID_OK:
+        filename = dlg.GetPath()
+        dlg.Destroy()
+    else:
+        return
+        
+    # Parse mapfile
+    mapobj = parse_mapfile(filename)
+    oldmapobj = context.mainwindow.canvas.Map().extension_umn_mapobj
+
+    # shows a dialog to select layers to import
+    selectedlayer = select_layer2import(context,mapobj)
+
+    # counter to show the numer of layer loaded into Tuban
+    layer_count = 0
+    # import settings to thuban only if one layer is selected
+    if len(selectedlayer) != 0:
+        # thuban map context
+        tb_map = context.mainwindow.canvas.Map()
+        # Check for each Layer if it is possible to show in Thuban
+        for layernr in selectedlayer:
+            maplayer = mapobj.get_layers()[layernr]
+            
+            #check if rasterlayer type
+            if maplayer.get_type() == 'raster':
+                add_rasterlayer(context, tb_map, mapobj, maplayer)
+                layer_count += 1
+    
+            #check if polygonlayer type
+            if ((maplayer.get_type() == 'polygon') or   
+                 (maplayer.get_type() == 'line') or
+                 (maplayer.get_type() == 'circle') or
+                 (maplayer.get_type() == 'point')):
+                add_polygonlayer(context, tb_map, mapobj, maplayer)
+                layer_count += 1
+            
+            if (maplayer.get_type() == 'annotation'):
+                add_annotationlayer(context, tb_map, mapobj, maplayer)
+
+        # show a message how many layer were loaded into thuban
+        # if the number of layers is not null
+        if layer_count != 0:
+            context.mainwindow.RunMessageBox(_('Layer loaded'),
+                                             _("%s Layer loaded into Thuban") % layer_count)
+
+def import_mapfile(context):
+    """
+    Import the mapfile from a file given by the user. After that parse
+    the mapfile with the mapscript parser to create all necessary objects.
+
+    Loaded polygon layer like polygon, line or point into thuban.
+    Raster layer are supported also.
+
+    context - the thuban context
+    """
+    # create a new session befor a mapfile is imported
+    if context.mainwindow.save_modified_session() != wx.ID_CANCEL:
+        context.application.SetSession(mainwindow.create_empty_session())
+        
+        # context.mainwindow.NewSession()
+        # open a dialog to select the mapfile to import
+        dlg = wx.FileDialog(context.mainwindow,
+                           _("Select MapFile file"), ".", "",
+                           _("UMN MapServer Mapfiles (*.map)|*.map|") +
+                           _("All Files (*.*)|*.*"),
+                           wx.OPEN|wx.OVERWRITE_PROMPT)
+        if dlg.ShowModal() == wx.ID_OK:
+            filename = dlg.GetPath()
+            dlg.Destroy()
+        else:
+            return
+        
+        # Parse mapfile
+        mapobj = parse_mapfile(filename)
+    
+        # shows a dialog to select layers to import
+        selectedlayer = select_layer2import(context,mapobj)
+        
+        # counter to show the numer of layer loaded into Tuban
+        layer_count = 0
+        # import settings to thuban only if one layer is selected
+        if len(selectedlayer) != 0:
+            # thuban map context
+            tb_map = context.mainwindow.canvas.Map()
+            # set the titel and projection
+            tb_map.SetTitle(mapobj.get_name())
+            set_projection_to_tb(tb_map,mapobj)
+
+            selectedlayer = list(selectedlayer)
+            # remove not selected layer from the mapfile
+            incount = 0
+            delcount = 0
+            newselect = []
+            for iii in range(0, len(mapobj.get_layers()), 1):
+                if iii in selectedlayer:
+                    newselect.append(selectedlayer[incount]-delcount)
+                    incount += 1
+                else:
+                    mapobj.remove_layer(iii-delcount)
+                    delcount += 1
+            selectedlayer = newselect
+           
+            # Check for each Layer if it is possible to show in Thuban
+            for layernr in selectedlayer:
+
+                maplayer = mapobj.get_layers()[layernr]
+                
+                #check if rasterlayer type
+                if maplayer.get_type() == 'raster':
+                    add_rasterlayer(context, tb_map, mapobj, maplayer)
+                    layer_count += 1
+        
+                #check if polygonlayer type
+                if ((maplayer.get_type() == 'polygon') or   
+                     (maplayer.get_type() == 'line') or
+                     (maplayer.get_type() == 'circle') or
+                     (maplayer.get_type() == 'point')):
+                    add_polygonlayer(context, tb_map, mapobj, maplayer)
+                    layer_count += 1
+                
+                if (maplayer.get_type() == 'annotation'):
+                    add_annotationlayer(context, tb_map, mapobj, maplayer)
+                    layer_count += 1
+    
+            # add the map object to thuban, to use it later
+            tb_map.extension_umn_mapobj = mapobj
+    
+            # show a message how many layer were loaded into thuban
+            # if the number of layers is not null
+            if layer_count != 0:
+                # get the extent from the map and set it in thuban
+                extentrect = mapobj.get_extent().get_rect()
+                # fit the new map extent to the window
+                context.mainwindow.canvas.FitRectToWindow(extentrect)
+                context.mainwindow.RunMessageBox(_('Layer loaded'),
+                                                 _("%s Layer loaded into Thuban") % layer_count)
+
+def parse_mapfile(filename):
+    """
+    Parse the mapfile.
+
+    Currently this is done using the mapscript module.
+    NOTE: It is also possible to use here an own parser
+    which could at aleast gain independency from the mapscript
+    module.
+
+    filename - the filename of the .map file
+    """
+    theMap = mapObj(filename)
+
+    return MF_Map(theMap)
+
+# check if an mapobj exists, to control the menuitem is available or not
+def _has_umn_mapobj(context):
+    return False
+    """Return true if a umn_mapobj exists"""
+    return hasattr(context.mainwindow.canvas.Map(), "extension_umn_mapobj")
+
+#create a new mapfile
+def create_new_mapfile(context):
+    theMap = MF_Map(mapObj(""))
+    context.mainwindow.canvas.Map().extension_umn_mapobj = theMap
+
+# ###################################
+#
+# Hook in MapServer Extension into Thuban
+#
+# ###################################
+
+# find the extensions menu (create it anew if not found)
+experimental_menu = main_menu.FindOrInsertMenu("experimental", _("Experimenta&l"))
+# find the extension menu and add a new submenu if found
+mapserver_menu = experimental_menu.FindOrInsertMenu("mapserver", _("&MapServer"))
+
+# register the new command
+registry.Add(Command("create_new_mapfile", _("Create new mapfile"), \
+                     create_new_mapfile, \
+		           helptext = _("Create a new empty mapscript MapObj")))
+# finally add the new entry to the extensions menu
+mapserver_menu.InsertItem("create_new_mapfile")
+
+# register the new command
+registry.Add(Command("import_mapfile", _("Import mapfile"), import_mapfile,
+                     helptext = _("Import a mapfile")))
+# finally add the new entry to the extensions menu
+mapserver_menu.InsertItem("import_mapfile",  after = "create_new_mapfile" )
+
+# register the new command
+registry.Add(Command("import_layer_from_mapfile", _("Import layer from mapfile"), 
+                     import_layer_from_mapfile,
+                     helptext = _("Import a layer from a mapfile"),
+                     sensitive = _has_umn_mapobj))
+# finally add the new entry to the extensions menu
+mapserver_menu.InsertItem("import_layer_from_mapfile", 
+                          after = "import_mapfile" )
+
+

Added: packages/thuban/branches/upstream/current/Extensions/umn_mapserver/sample/README
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/umn_mapserver/sample/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/umn_mapserver/sample/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,21 @@
+Howto use the sample with thuban:
+
+iceland.map: 
+        start Thuban from the main CVS thuban directory.
+        (the paths to the Iceland datafiles are relative
+        and will work then)
+
+
+Howto view this sample in UMN MapServer (webserver):
+
+	Copy the three files included in this directory to a new directory on
+	your webserver. For example "Iceland". To use the iceland data you
+	must edit the data path in iceland.map, so that it matches to the
+	directory where	the data is. At the moment the data path is relative
+	to this directory. The data is in the thuban/Data/iceland directory. 
+
+iceland.html:
+        the template for the mapfile.
+
+index.html:
+        the initialisation file for the Iceland Application on web.

Added: packages/thuban/branches/upstream/current/Extensions/umn_mapserver/test/README
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/umn_mapserver/test/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/umn_mapserver/test/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,6 @@
+This directory contains tests of the umn_mapserver extension.
+
+Howto run test (assume thuban source is under ~/project):
+
+export PYTHONPATH=~/project/thuban:~/project/thuban/Lib:~/project/thuban/test
+python test_mapserver.py

Added: packages/thuban/branches/upstream/current/Extensions/umn_mapserver/test/test_mapserver.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/umn_mapserver/test/test_mapserver.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/umn_mapserver/test/test_mapserver.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,396 @@
+# -*- coding:latin1 -*-
+
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Jan Schüngel <jschuengel at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Tests for UMN Mapserver extension.
+"""
+
+__version__ = "$Revision: 2307 $"
+# $Source$
+# $Id: test_mapserver.py 2307 2004-07-28 12:46:19Z jschuengel $
+
+# Import the testmodul from python
+import unittest
+
+from mapscript import mapObj
+
+# Import  necessary classes from Thuban
+from Thuban.Model.color import Color, Transparent
+
+from Thuban.Model.proj import Projection
+
+# Import the Classes to test
+from Extensions.umn_mapserver.mapfile import MF_Color, \
+    MF_Rectangle, MF_Style, MF_Map, MF_Projection, \
+    MF_Class, MF_Layer, MF_Metadata, MF_Outputformat, \
+    MF_Symbol, MF_SymbolSet, MF_Scalebar, \
+    MF_Label, MF_Legend, MF_Web
+
+from Extensions.umn_mapserver.mapfile import shp_type
+
+from Extensions.umn_mapserver.mf_import import create_rangeexpression
+
+class mapserver_generalClasses(unittest.TestCase):
+
+    def setUp(self):
+        """
+        Running this funktion befor each test
+        """
+        # using the sample map
+        testMapfile = 'test.map'
+        self.testMap = mapObj(testMapfile)
+        self.eq = self.assertEquals
+
+
+    def test_MF_Color(self):
+        """
+        Testing Color Objects from MapServer.
+        """
+        # IMAGECOLOR  255 255 255
+        testcolor = MF_Color(self.testMap.imagecolor)        
+        self.eq(testcolor.get_red(), 255)
+        self.eq(testcolor.get_green(), 255)
+        self.eq(testcolor.get_blue(), 255)
+        
+        # set Color with Thuban color obj
+        testthubancolor = Color(0.5,1,0)
+        testcolor.set_thubancolor(testthubancolor)
+        self.eq(testcolor.get_red(),127)
+        self.eq(testcolor.get_green(),255)
+        self.eq(testcolor.get_blue(),0)
+        
+        # check if Thubancolor is set correct
+        testtbcolor = testcolor.get_thubancolor()
+        self.eq(testtbcolor.red, 0.5)
+        self.eq(testtbcolor.green, 1)
+        self.eq(testtbcolor.blue, 0)
+
+
+    def test_MF_Rectangle(self):
+        """
+        Testing rectangle objects by example like
+        the mapfile parameter extent.
+        """
+        # EXTENT  622877.17 7019306.94 1095667.78 7447709.31 
+        testrect = MF_Rectangle(self.testMap.extent)        
+        self.eq(testrect.get_minx(), 622877.17)
+        self.eq(testrect.get_miny(), 7019306.94)
+        self.eq(testrect.get_maxx(), 1095667.78)
+        self.eq(testrect.get_maxy(), 7447709.31)
+        
+        # Set a new Rectangle and test if is set correctly
+        testrect.set_rect(50,50,200,200)
+        self.eq(testrect.get_rect(), (50,50,200,200))
+        self.eq(testrect.get_minx(), 50)
+        self.eq(testrect.get_miny(), 50)
+        self.eq(testrect.get_maxx(), 200)
+        self.eq(testrect.get_maxy(), 200)
+
+
+    def test_MF_Metadata(self):
+        """
+        Testing the meta data
+        """
+        # set up to keys to test
+        testmetadata = MF_Metadata(self.testMap)
+        self.eq(self.testMap.getMetaData("titel"), "Iceland Test")
+        testmetadata.add_metadata("test", "test eintrag")
+        self.eq(testmetadata.get_metadatabykey("test"),"test eintrag")
+        
+        # generate the MetaData from the testMap
+        testMap2 = MF_Map(self.testMap)
+        testmetadata = testMap2.get_metadata()
+        self.eq(testmetadata.get_metadatabykey("titel"),"Iceland Test")
+
+
+class mapserver_Classes(unittest.TestCase):
+
+    def setUp(self):
+        """
+        Running this funktion befor each test
+        """
+        # using the sample map
+        testMapfile = 'test.map'
+        self.testMap = mapObj(testMapfile)
+        self.eq = self.assertEquals
+
+
+    def test_MF_OutputFormat(self):
+        """
+        Testing the outputformat object
+        """
+        testoutputformat = MF_Outputformat(self.testMap.getOutputFormatByName("png"))
+        self.eq(testoutputformat.get_name(),"png")
+
+
+    def test_MF_Symbolset(self):
+        """
+        Testing the symbolset
+        """
+        testsymbolset = MF_SymbolSet(self.testMap.symbolset)
+        self.eq(testsymbolset.get_symbol(1).get_name(), "circle") 
+
+
+    def test_MF_Symbol(self):
+        """
+        Testing the symbol object
+        """
+        testsymbol = MF_Symbol(self.testMap.symbolset.getSymbolByName("circle"))
+        self.eq(testsymbol.get_name(), "circle")
+        assert(testsymbol.get_symbolObj(), self.testMap.symbolset.getSymbolByName("circle"))
+        
+        testsymbol.set_filled(True)
+        self.eq(testsymbol.get_filled(), True)
+        
+        testsymbol.set_type(4)
+        self.eq(testsymbol.get_type(), 4)
+
+
+    def test_MF_Class(self):
+        """
+        Testing the class object.
+        """        
+        # only test the number of styles at the moment
+        testclass = MF_Class(self.testMap.getLayer(0).getClass(0))
+        self.eq (len(testclass.get_styles()), self.testMap.getLayer(0).getClass(0).numstyles)
+
+        # check the name
+        self.eq(testclass.get_name(), "testclass")
+        testclass.set_name("checkout")
+        self.eq(testclass.get_name(), "checkout")
+
+        # check the expressionstring
+        testclass = MF_Class(self.testMap.getLayer(2).getClass(0))
+        self.eq(testclass.get_expressionstring(), '"9"')
+        testclass.set_expressionstring("3")
+        self.eq(testclass.get_expressionstring(), '"3"')
+
+
+    def test_MF_Layer(self):
+        """
+        Testing the layer object with some
+        sample data and classes.
+        """
+        testlayer = MF_Layer(self.testMap.getLayer(2))
+        # NAME 'political' only from layer 1
+        self.eq(testlayer.get_name(), 'cultural')
+        testlayer.set_name('checkout')
+        self.eq(testlayer.get_name(), 'checkout')        
+        # check number of classes
+        self.eq(len(testlayer.get_classes()), self.testMap.getLayer(2).numclasses)
+        # check classitem
+        self.eq(testlayer.get_classitem(), "CLPOINT_")
+        testlayer.set_classitem("CLCHECK")
+        self.eq(testlayer.get_classitem(), "CLCHECK")
+        # check data
+        self.eq(testlayer.get_data(), "cultural_landmark-point")
+        testlayer.set_data("test.shp")
+        # .shp will be cutted becouse the source is always a .shp,
+        # or maybe a grafik
+        self.eq(testlayer.get_data(), "test")
+        # check projection (used the pojection obj a little bit)
+        self.eq(testlayer.get_projection().get_projection(), "+proj=latlong+ellps=clrk66")
+        # TYPE POLYGON
+        self.eq(testlayer.get_type(), "point")
+        testlayer.set_type("circle")
+        self.eq(testlayer.get_type(), "circle")
+        # Check status
+        # 0 = off, 1 = on, 2 = default
+        self.eq(testlayer.get_status(), True)
+        testlayer.set_status(False)
+        self.eq(testlayer.get_status(), False)
+
+
+    def test_MF_Map(self):
+        """
+        Testing the mapfile object with samples.
+        """
+        testMapp = MF_Map(self.testMap)
+        # NAME 'ISLAND'
+        self.eq(testMapp.get_name(), 'ISLAND')
+        self.eq(len(testMapp.get_layers()), self.testMap.numlayers)
+    
+        # test see in test_MF_Projection
+        testproj = Projection(['proj=utm', 'ellps=clrk66', 'zone=26', 'north'])
+        testMapp.set_projection(testproj)
+        self.eq(testMapp.get_projection().get_params(), ['proj=utm', 'ellps=clrk66', 'zone=26', 'north'])
+        
+        self.eq(testMapp.get_size(), (600,450))
+        testMapp.set_size(500,600)
+        self.eq(testMapp.get_size(), (500,600))
+
+
+    def test_MF_Scalebar(self):
+        """
+        Test the Scalebarobj from the testfile
+        """
+        testscalebar = MF_Scalebar(self.testMap.scalebar)
+        self.eq(testscalebar.get_position(mode="string"),"ll")
+        self.eq(testscalebar.get_position(), 3)
+        self.eq(testscalebar.get_intervals(), 4)
+        self.eq(testscalebar.get_status(mode="string"), "OFF")
+
+
+    def test_MF_Label(self):
+        """
+        Test a Label object. In this test use the Label from 
+        from the Scalebarobj in the testfile
+        """
+        testlabel = MF_Label(self.testMap.scalebar.label)
+        self.eq(testlabel.get_force(), False)
+        self.eq(testlabel.get_buffer(),0)
+        self.eq(testlabel.get_type(), "bitmap") 
+
+
+    def test_MF_Legend(self):
+        """
+        test the legend object from the testfile
+        """
+        testlegend = MF_Legend(self.testMap.legend)
+        self.eq(testlegend.get_status(), False)
+        testlegend.set_status(True)
+        self.eq(testlegend.get_status(), True)
+        testlegend.set_position("ul")
+        self.eq(testlegend.get_position(mode="string"), "ul")
+        testlegend.set_keyspacing(4,5)
+        self.eq(testlegend.get_keyspacing(), (4,5))
+        testlegend.set_keysize(6,7)
+        self.eq(testlegend.get_keysize(), (6,7))
+
+
+    def test_MF_Projection(self):
+        """
+        Projection object is tested with parameters
+        and an epsg code.
+        """
+        # proj=utm
+        # ellps=clrk66
+        # zone=26
+        # north
+        testproj = MF_Projection(self.testMap.getProjection())
+        if testproj.get_params():
+            self.eq(testproj.get_params(), ['proj=utm','ellps=WGS84','zone=26','north']) 
+        
+        #"init=epsg:26915"
+        if testproj.get_epsgcode():
+            self.eq(testproj.get_epsgcode(), '26915') 
+
+
+    def test_MF_Style(self):
+        """
+        Tests a style object with all parameters.
+        """
+        teststyle = MF_Style(self.testMap.getLayer(0).getClass(0).getStyle(0))
+        # OUTLINECOLOR 0 0 0
+        self.eq(teststyle.get_outlinecolor().get_red(), 0)
+        # COLOR 100 200 100
+        self.eq(teststyle.get_color().get_red(), 100)
+        self.eq(teststyle.get_color().get_green(), 200)
+        self.eq(teststyle.get_color().get_blue(), 100)
+        # SIZE 2
+        self.eq(teststyle.get_size(), 2)
+
+
+    def test_MF_Web(self):
+        """
+        Tests a web object
+        """
+        testweb = MF_Web(self.testMap.web)
+        self.eq(testweb.get_imagepath(), "/tmpimg/")
+        testweb.set_imagepath("/tmppathset/")
+        self.eq(testweb.get_imagepath(), "/tmppathset/")
+        self.eq(testweb.get_imageurl(),"/tmpurl/")
+        testweb.set_imageurl("/tmpurlset/")
+        self.eq(testweb.get_imageurl(), "/tmpurlset/")
+
+
+class mapserver_mf_import(unittest.TestCase):
+
+    def setUp(self):
+        """
+        Running this funktion befor each test
+        """
+        # using the sample map
+        testMapfile = 'test.map'
+        self.testMap = mapObj(testMapfile)
+        self.eq = self.assertEquals
+
+
+    def test_create_rangeexpression(self):
+        """
+        testing the range expression creation from the code in the mapfile
+        """
+        # the expressions to test
+        # these expresions are like in thuban
+        test1 = "([ATTR] >= 1 AND [ATTR] <= 100)" # [min,max]
+        code,expr = create_rangeexpression(test1[1:-1])
+        self.eq(code, "ATTR")
+        self.eq(expr,"[1;100]")
+        test2 = "([ATTR] >= 1 AND [ATTR] < 100)" # [min,max[
+        code,expr = create_rangeexpression(test2[1:-1])
+        self.eq(code, "ATTR")
+        self.eq(expr,"[1;100[")
+        test3 = "([ATTR] > 1 AND [ATTR] <= 100)" # ]min,max]
+        code,expr = create_rangeexpression(test3[1:-1])
+        self.eq(code, "ATTR")
+        self.eq(expr,"]1;100]")
+        test4 = "([ATTR] > 1 AND [ATTR] < 100)" # ]min,max[
+        code,expr = create_rangeexpression(test4[1:-1])
+        self.eq(code, "ATTR")
+        self.eq(expr,"]1;100[")
+        
+        test5 = "([ATTR] <= 100)" # [-oo,max] , ]-oo,max]
+        code,expr = create_rangeexpression(test5[1:-1])
+        self.eq(code, "ATTR")
+        self.eq(expr,"[-oo;100]")
+        test6 = "([ATTR] < 100)" # [-oo,max[ , ]-oo,max[
+        code,expr = create_rangeexpression(test6[1:-1])
+        self.eq(code, "ATTR")
+        self.eq(expr,"[-oo;100[")
+        test7 = "([ATTR] >= 1)" # [min,oo] , [min, oo[
+        code,expr = create_rangeexpression(test7[1:-1])
+        self.eq(code, "ATTR")
+        self.eq(expr,"[1;oo]")
+        test8 = "([ATTR] > 1)" # ]min,oo] , ]min, oo[
+        code,expr = create_rangeexpression(test8[1:-1])
+        self.eq(code, "ATTR")
+        self.eq(expr,"]1;oo]")
+        
+        # value equal, works but is not really usefull
+        test9= "([ATTR] < 1 AND [ATTR] >= 1)"
+        code,expr = create_rangeexpression(test9[1:-1])
+        self.eq(code, "ATTR")
+        self.eq(expr,"[1;1[")
+        
+        # works but must be changed the order
+        test10= "([ATTR] <= 100 AND [ATTR] >= 1)"
+        code,expr = create_rangeexpression(test10[1:-1])
+        self.eq(code, "ATTR")
+        self.eq(expr,"[1;100]")
+        
+        #singleton not implemented yet
+        test11 = "([ATTR] = 1)"
+        code,expr = create_rangeexpression(test11[1:-1])
+        self.eq(code, None)
+        self.eq(expr,"singleton creation not implemented yet")
+
+        # Attributes not equal
+        test12= "([ATTR] < 100 AND [ATTR2] >= 1)"
+        code,expr = create_rangeexpression(test12[1:-1])
+        self.eq(code, None)
+        self.eq(expr,"Attributes not equal")
+        # dont works, is not supported by thuban
+        test13="([ATTR] > 100 AND [ATTR] < 1)"
+        code,expr = create_rangeexpression(test13[1:-1])
+        self.eq(code, None)
+        self.eq(expr,"values are wrong")
+
+
+if __name__ == '__main__':
+    unittest.main()

Added: packages/thuban/branches/upstream/current/Extensions/wms/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,28 @@
+# Copyright (c) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+# first try out whether we can import the required module
+# of the PyOGCLib.
+ok = True
+try:
+    import ogclib.WMSClient
+except:
+    print "Problems with PyOGCLib (not installed?)"
+    ok = False
+
+if ok:
+    import wms
+
+    from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+    from Thuban import _
+
+    ext_registry.add(ExtensionDesc(
+        name = 'WMS',
+        version = '0.2.0',
+        authors= [ 'Jan-Oliver Wagner', 'Martin Schulze' ],
+        copyright = '2003, 2004 Intevation GmbH',
+        desc = _("Provide layers via OGC WMS.")))

Added: packages/thuban/branches/upstream/current/Extensions/wms/capabilities.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/capabilities.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/capabilities.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,192 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Maintain WMS Capabilities
+
+Inherits methods from WMSCapabilitiesParser
+
+class WMSCapabilities:
+    __init__ (resource xor filename xor nothing)
+
+    getErrorMsg()
+
+    fetchCapabilities(resource)
+    saveCapabilities(filename)
+    loadCapabilities(filename)
+    printCapabilities()
+
+    getVersion()
+
+Requirements:
+    - PyOGCLib <http://www.sourceforge.net/projects/pyogclib>
+
+Requires the ogclib installed regularily on the system or checked out
+next to the Thuban checkout.
+
+If this module is executed solitarily, it will fetch the capabilities
+of the frida service and store them in the local file
+frida_capabilities.xml for later processing.
+
+"""
+
+__version__ = "$Revision: 2152 $"
+# $Source$
+# $Id: capabilities.py 2152 2004-04-01 15:34:25Z joey $
+
+import os
+
+# ----------------------------------------------------------------------
+# FIXME: Temporary code until PyOGCLib is a standard requirement
+
+from sys import path
+
+# Assume the PyOGCLib to be checked out next to the thuban main directory
+pyogclib = "../../../PyOGCLib"
+if os.path.isdir(pyogclib) and os.path.isdir(pyogclib + "/ogclib"):
+    path.insert(0, pyogclib)
+
+# We use gettext, so we need to import it and hence need to adjust the
+# path again
+if __name__ == "__main__":
+    path.insert(0, "../../")
+
+# ----------------------------------------------------------------------
+
+from Thuban import _
+
+from ogclib.WMSClient import WMSClient
+from parser import WMSCapabilitiesParser
+
+class WMSCapabilities(WMSClient, WMSCapabilitiesParser):
+    """
+    Thuban class to maintain capabilities.  This class provides
+    methods to fetch, save and load capabilities as well as methods to
+    retrieve particular information from the fetched or loaded
+    capabilities XML.
+
+    If an error occured during processing an error text is assigned to
+    self.errorMsg.  If everything went fine, this variable is set to
+    None.  The current value can be retrieved by the getErrorMsg()
+    method.
+    """
+
+    capabilities = None
+    errorMsg = None
+    wmsVersion = None
+
+    def __init__(self, *parm):
+        """
+        Initialises Capabilities with one optional parameter
+
+        param can be either a URL or a filename:
+
+        filename -- load capabilities from file
+        url -- fetch capabilities from network
+        """
+
+        if parm and parm[0]:
+            if os.path.isfile(parm[0]):
+                self.loadCapabilities(parm[0])
+            else:
+                if parm[0].find("http://", 0) == 0:
+                    self.fetchCapabilities(parm[0])
+                else:
+                    self.errorMsg \
+                        = _("Resource '%s' is neither local file nor URL") \
+                        % parm[0]
+
+
+    def getErrorMsg(self):
+        return self.errorMsg
+
+
+    def fetchCapabilities(self, resource):
+        """
+        Fetches the WMS capabilities from an Internet resource
+
+        WMS Protocol version 1.1 is tried first, then 1.0.  The
+        protocol version used can be queried by the getVersion()
+        method for later use.  If both tries fail, errorMsg will be
+        set accordingly, which can be fetched with getErrorMsg().
+        """
+
+        self.wmsVersion = "1.1"
+        self.capabilities = self.getCapabilities(resource, self.wmsVersion)
+        if not self.capabilities:
+            self.wmsVersion = "1.0"
+            self.capabilities = self.getCapabilities(resource, self.wmsVersion)
+            if not self.capabilities:
+                self.wmsVersion = None
+                self.errorMsg \
+                    = _("Resource '%s' "
+                        "does support neither WMS version 1.1 nor 1.0") \
+                        % resource
+
+        if self.capabilities:
+            self.grok(self.capabilities)
+
+
+    def saveCapabilities(self, fname):
+        """Save capabilities to local file"""
+
+        if self.capabilities is None:
+            self.errorMsg = _("No capabilities available")
+        else:
+            try:
+                out = open(fname, "w")
+                out.write(self.capabilities)
+                out.close()
+            except IOError:
+                self.errorMsg = _("Can't open file '%s' for writing") % fname
+
+
+    def loadCapabilities(self, fname):
+        """Load capabilities from a local file"""
+
+        try:
+            input = open(fname, "r")
+            self.capabilities = input.read()
+            input.close()
+            self.grok(self.capabilities)
+        except IOError:
+            self.errorMsg = _("Can't open file '%s' for reading") % fname
+
+
+    def printCapabilities(self):
+        """Prints capabilities to stdout"""
+
+        print self.capabilities
+
+
+    def getVersion(self):
+        """
+        Returns the WMS protocol version
+
+        If no capabilities could be fetched, None is returned.
+        """
+        return self.wmsVersion
+
+
+if __name__ == "__main__":
+    capabilities \
+        = WMSCapabilities("http://frida.intevation.org/cgi-bin/frida_wms?")
+    if capabilities.getErrorMsg() is None:
+        capabilities.saveCapabilities("frida_capabilities.xml")
+    else:
+        print "Error: " + capabilities.getErrorMsg()

Added: packages/thuban/branches/upstream/current/Extensions/wms/domutils.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/domutils.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/domutils.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,75 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Convenience routines for handling of Document Object Model (DOM)
+nodes.
+
+For more information on DOM see <http://www.zytrax.com/tech/dom/guide.html>.
+
+"""
+
+def listChildNodes (node):
+    """
+    Prints a list of all child DOM nodes for the given node.  This
+    function is normally only used for inspection of a DOM tree during
+    development.
+    """
+    print "Node %s has %d children" % (node.nodeName, node.childNodes.length)
+    for i in range (node.childNodes.length):
+        print "  %d: %s" % (i, node.childNodes[i].nodeName)
+
+
+def listAttributes (node):
+    """
+    Prints a list of all DOM attributes for the given node.  This
+    function is normally only used for inspection of a DOM tree during
+    development.
+    """
+    print "Node %s has %d attributes" % (node.nodeName, node.attributes.length)
+    for key in node.attributes.keys():
+        print "  %s=%s" % (key, node.attributes.get(key).nodeValue)
+
+
+# Can't use node.getElementsByTagName(name) since it traverses the XML
+# data recursively and we need hierarchy information as well in order
+# to get inheritance of attributes implemented properly.
+#
+def getElementsByName (node, name):
+    """
+    Returns a list of child DOM nodes whose nodeName matches given
+    string.
+    """
+    res = []
+    for i in range (node.childNodes.length):
+        if node.childNodes[i].nodeName == name:
+            res.append(node.childNodes[i])
+    return res
+
+
+def getElementByName (node, name):
+    """
+    Returns the first child DOM node whose nodeName matches given
+    string.
+    """
+    try:
+        return getElementsByName (node, name)[0]
+    except IndexError:
+        return None
+
+

Added: packages/thuban/branches/upstream/current/Extensions/wms/infodialog.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/infodialog.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/infodialog.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,117 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Information dialog to display various information about a WMS layer.
+
+class wmsInfoDialog(ThubanFrame):
+    __init__
+
+    dialog_layout(text)
+
+    calcText(layer)
+    
+"""
+
+__version__ = "$Revision: 2555 $"
+# $Source$
+# $Id: infodialog.py 2555 2005-02-06 16:47:34Z joey $
+
+from Thuban import _
+from Thuban.UI.dialogs import ThubanFrame
+
+from wxPython.wx import wxBoxSizer, wxTextCtrl, wxVERTICAL, \
+    wxHORIZONTAL, wxTE_READONLY, wxTE_MULTILINE, wxTE_LINEWRAP, \
+    wxEXPAND, wxALL, wxButton, wxALIGN_CENTER_HORIZONTAL, wxID_OK, \
+    EVT_BUTTON
+
+
+class wmsInfoDialog(ThubanFrame):
+    """
+    Representation for a simple information dialog
+
+    This dialog will display the title of the WMS resource
+    """
+
+    def __init__(self, parent, name, layer, *args, **kw):
+        """
+        Build the information dialog
+        """
+        title = _("WMS Information")
+        ThubanFrame.__init__(self, parent, name, title)
+
+        self.dialog_layout(self.calcText(layer))
+
+
+    def dialog_layout(self, text):
+        """
+        Set up the information dialog
+        """
+
+        vbox = wxBoxSizer(wxVERTICAL)
+
+        textBox = wxTextCtrl(self, -1, text,
+                             style=wxTE_READONLY|wxTE_MULTILINE|wxTE_LINEWRAP)
+        w, h = (500, 300)
+        textBox.SetSizeHints(w, h)
+        textBox.SetSize((w, h))
+        
+        vbox.Add(textBox, 1, wxEXPAND|wxALL, 10)
+        
+        buttons = wxBoxSizer(wxHORIZONTAL)
+        buttons.Add(wxButton(self, wxID_OK, _("Close")), 0, wxALL, 4)
+        vbox.Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 10)
+        
+        EVT_BUTTON(self, wxID_OK, self.OnClose)
+        
+        self.SetAutoLayout(True)
+        self.SetSizer(vbox)
+        vbox.Fit(self)
+        vbox.SetSizeHints(self)
+
+
+    def calcText(self, layer):
+        """
+        Generate the text to be displayed in the information window
+
+        It will use several nodes returned by the GetCapabilities
+        request, such as the title, the abstract, fees and access
+        constraints, if they are documented.
+        """
+
+        text = ''
+
+        foo = layer.capabilities.getTitle()
+        if foo != "":
+            text += foo.encode('latin1') + "\n\n"
+
+        foo = layer.capabilities.getAbstract()
+        if foo != "":
+            text += foo + "\n\n"
+
+        foo = layer.capabilities.getFees()
+        if foo != "":
+            text += _("Fees:") + "\n\n" + foo + "\n\n"
+
+        foo = layer.capabilities.getAccessConstraints()
+        if foo != "":
+            text += _("Acces Constraints:") + "\n\n" + foo + "\n\n"
+
+        text += "URL: " + layer.url
+
+        return text

Added: packages/thuban/branches/upstream/current/Extensions/wms/layer.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/layer.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/layer.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,339 @@
+# Copyright (c) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Graphic Layer via OGC WMS.
+
+class WMSLayer:
+    __init__()
+
+    LatLongBoundingBox()
+    BoundingBox()
+
+    getFormat(format)
+    calcFormat(formats)
+
+    getFormats()
+    getLayers()
+    getLayerTitle()
+
+    getWMSFormat()
+    setWMSFormat(format)
+
+    GetMapImg(width, height, bbox)
+
+Requirements:
+    - PyOGCLib <http://www.sourceforge.net/projects/pyogclib>
+
+Requires the ogclib installed regularily on the system or checked out
+next to the Thuban checkout.  Or set the PYTHONPATH to the PyOGCLib
+directory before starting Thuban.
+
+"""
+
+__version__ = "$Revision: 2438 $"
+# $Source$
+# $Id: layer.py 2438 2004-12-09 10:34:03Z joey $
+
+
+from Thuban.Model.layer import BaseLayer
+from Thuban.Model.resource import get_system_proj_file, EPSG_PROJ_FILE, \
+     EPSG_DEPRECATED_PROJ_FILE
+from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
+
+from capabilities import WMSCapabilities
+
+from ogclib.WMSClient import WMSClient
+
+
+def epsg_code_to_projection(epsg):
+    """Find the projection for the given epsg code.
+
+    epsg -- EPSG code as string
+    """
+    proj_file, warnings = get_system_proj_file(EPSG_PROJ_FILE)
+
+    for proj in proj_file.GetProjections():
+        if proj.EPSGCode() == epsg:
+            return proj
+    proj_file, warnings = get_system_proj_file(EPSG_DEPRECATED_PROJ_FILE)
+    for proj in proj_file.GetProjections():
+        if proj.EPSGCode() == epsg:
+            return proj
+    return None
+
+
+class WMSLayer(BaseLayer):
+    """
+    WMS Layer
+
+    This layer incorporates all methods from the Thuban BaseLayer and
+    adds specific methods for operating with a WMS server.
+    """
+
+    def __init__(self, title, url):
+        """Initializes the WMSLayer.
+
+        title -- Title of this layer.
+        url -- URL of the WMS-Server wich must contain '?'
+
+        If an error occured, self.error_msg is a string describing
+        the problem(s). Else, self.error_msg is None.
+        """
+        BaseLayer.__init__(self, title, visible = True, projection = None)
+        self.url = url
+        self.bbox = None
+        self.latlonbbox = None
+        self.error_msg = None
+        self.wms_layers = []
+        self.capabilities = None
+
+        # Change the cursor to demonstrate that we're busy but working
+        ThubanBeginBusyCursor()
+        self.capabilities = WMSCapabilities(url)
+        ThubanEndBusyCursor()
+
+        # name of the top layer of the remote map
+        foo = self.capabilities.getLayers()
+        if len(foo) == 0:
+            self.error_msg = _('No layers found in remote resource:\n'\
+                               '%s') % url
+            return
+        top_layer = foo[0]
+        self.wms_layers = [top_layer]
+
+        # first projection of the top layer
+        foo = self.capabilities.getLayerSRS(top_layer)
+        if len(foo) == 0:
+            self.error_msg = _('No LatLonBoundingBox found for top layer %s')\
+                             % top_layer
+            return
+        top_srs = foo[0]
+
+        # BoundingBox of the top layer
+        bbox = self.capabilities.getLayerBBox(top_layer, top_srs)
+        if len(bbox) == 0:
+            self.error_msg = _('No BoundingBox found for layer %s and EPSG:')\
+                             % (top_layer, top_srs)
+            return
+        self.bbox = (float(bbox['minx']),
+                     float(bbox['miny']),
+                     float(bbox['maxx']),
+                     float(bbox['maxy']))
+
+        # LatLonBox of the top layer
+        bbox = self.capabilities.getLayerLatLonBBox(top_layer)
+        self.latlonbbox = (float(bbox['minx']),
+                           float(bbox['miny']),
+                           float(bbox['maxx']),
+                           float(bbox['maxy']))
+
+        # get projection
+        p = epsg_code_to_projection(top_srs)
+        self.SetProjection(p)
+
+        if p is None:
+            self.error_msg = _('EPSG projection code %s not found!\n'\
+                               'Setting projection to "None".\n'\
+                               'Please set an appropriate projection yourself.'\
+                               % top_srs)
+
+        # pre-determine the used format
+        self.wmsformat, self.format = \
+            self.calcFormat(self.capabilities.getFormats())
+        if self.wmsformat is None:
+            self.error_msg = \
+                _('No supported image format found in remote resource')
+            return
+
+        # get and set the title
+        self.SetTitle(self.capabilities.getTitle().encode('latin1', 'replace'))
+
+
+    def LatLongBoundingBox(self):
+        """
+        Return the layer's bounding box in lat-lon
+        """
+        return self.latlonbbox
+
+
+    def BoundingBox(self):
+        """
+        Return the layer's bounding box in the intrinsic coordinate system
+        """
+        return self.bbox
+
+
+    def getFormat(self, format):
+        """
+        Return the image format for the render engine
+
+        format -- format as returned by the WMS server
+
+        If no mapping was found, None is returned.
+
+        This routine uses a simple heuristic in order to find the
+        broken down image format to be used with the internal render
+        engine.
+
+        An exception rule is implemented in order to not accept
+        image/wbmp or WBMP which refers to WAP bitmap format and is
+        not supported by the included render engine.
+        """
+        fmap = {'png' : "PNG",
+                'jpeg': "JPEG",
+                'jpg' : "JPEG",
+                'tif' : "TIFF",
+                'gif' : "GIF",
+                'wbmp': None,
+                'bmp' : "BMP"}
+
+        for f in fmap.keys():
+            if format.lower().find(f) > -1:
+                    return fmap[f]
+        return None
+
+        
+    def calcFormat(self, formats):
+        """
+        Calculate the preferred image format
+
+        formats -- list of formates as returned by the WMS server
+
+        The following priority is used:
+        - PNG
+        - JPEG
+        - TIFF
+        - GIF
+        - BMP
+
+        If no matching format was found, None, None will be returned.
+
+        An exception rule is implemented in order to not accept
+        image/wbmp or WBMP which refers to WAP bitmap format and is
+        not supported by the included render engine.
+        """
+        prio = ['png', 'gif', 'jpeg', 'bmp']
+        for p in prio:
+            for f in formats:
+                if f.lower().find(p) > -1:
+                    if f.lower().find('wbmp') == -1:
+                        return f, self.getFormat(f)
+        return None, None
+        
+
+    def getFormats(self):
+        """
+        Return the list of supported image formats by the WMS server
+
+        These formats may be used in the WMS GetMap request.  Data is
+        retrieved from the included WMSCapabilities object.
+
+        The called method from WMSCapabilities will default to
+        'image/jpeg' if no format is recognised in XML Capabilities,
+        assuming that JPEG will always be supported on the server side
+        with this encoding.
+        """
+        return self.capabilities.getFormats()
+
+
+    def getLayers(self):
+        """
+        Return the list of layer names supported by the WMS server
+
+        Data is retrieved from the included WMSCapabilities object.
+
+        Only named layers will be returned, since a layer may have a
+        title but doesn't have to have a name associated to it as
+        well.  If no layers were found, an empty list is returned.
+        """
+        return self.capabilities.getLayers()
+
+
+    def getLayerTitle(self, layer):
+        """
+        Return the title of the named layer
+
+        Data is retrieved from the included WMSCapabilities object.
+
+        If no such title or no such layer exists, an empty string is
+        returned.
+        """
+        return self.capabilities.getLayerTitle(layer)
+
+
+    def getWMSFormat(self):
+        """
+        Return the image format that is used for WMS GetMap requests
+        """
+        return self.wmsformat
+
+
+    def setWMSFormat(self, format):
+        """
+        Set the image format that is used for WMS GetMap requests
+
+        format -- format, one of getFormats()
+        """
+        self.wmsformat = format
+        self.format = self.getFormat(format)
+
+
+    def getVisibleLayers(self):
+        """
+        Return the list of names for all visible layers
+
+        """
+        return self.wms_layers
+
+
+    def setVisibleLayers(self, layers):
+        """
+        Set the list of names for all visible layers
+
+        """
+        self.wms_layers = layers
+
+
+    def GetMapImg(self, width, height, bbox):
+        """
+        Retrieve a new map from the WMS server and return it
+
+        width -- width in pixel of the desired image
+        height -- height in pixel of the desired image
+        bbox -- array of min(x,y) max(x,y) in the given SRS
+
+        SRS and used image format will be retrieved from within the
+        layer itself.
+        """
+        bbox_dict = { 'minx': bbox[0], 'miny': bbox[1],
+                      'maxx': bbox[2], 'maxy': bbox[3] }
+
+        # Change the cursor to demonstrate that we're busy but working
+        ThubanBeginBusyCursor()
+
+        wmsclient = WMSClient()
+
+        epsg_id = int(self.GetProjection().EPSGCode())
+
+        wms_response = wmsclient.getMap(self.url, self.wmsformat, width, height,
+                                   epsg_id, bbox_dict,
+                                   self.wms_layers, version = self.capabilities.getVersion())
+        ThubanEndBusyCursor()
+        return wms_response, self.format

Added: packages/thuban/branches/upstream/current/Extensions/wms/parser.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/parser.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/parser.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,527 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Inspect WMS Capabilities for later processing.
+
+Information should only be retrieved with the proper get*() methods.
+
+class WMSCapabilitiesParser:
+    __init__()
+
+    grok(string)
+
+    getTitle()
+    getAbstract()
+    getFees()
+    getAccessConstraints()
+    getFormats()
+    getLayers()
+    getSRS()
+
+    getLayerTitle(layer)
+    getLayerSRS(layer)
+    getLayerLatLonBBox(layer)
+    getLayerBBox(layer, srs)
+
+    isQueryable(layer)
+"""
+
+__version__ = "$Revision: 2439 $"
+# $Source$
+# $Id: parser.py 2439 2004-12-09 10:37:44Z joey $
+
+import xml.dom.minidom
+from xml.dom import Node
+
+from domutils import getElementsByName, getElementByName
+
+from Thuban import _
+
+class WMSCapabilitiesParser:
+    """
+    Thuban class to parse capabilities supplied as large string.
+
+    This class provides methods to parse and retrieve particular
+    information from the WMS capabilities XML.  Information should
+    only be extracted by the respective get*() methods.
+    """
+
+    layers = None
+    title = None
+    abstract = None
+    fees = None
+    access = None
+    formats = None
+    error = None
+
+
+    def __init__(self):
+        """
+        Initialises an instance in this class.
+        """
+
+        # Note that we must not initialise internal variables of the
+        # class in a mutable way or it will be shared among all
+        # instances.  None is immutable, [] is not.
+        self.error = []
+
+
+    def grok(self, data):
+        """
+        Parses the XML response to a WMS GetCapabilities request.
+
+        Internal datastructure of the class will be filled.
+        Information should only be retrieved with the respective
+        get*() methods.
+        """
+        xml_dom = xml.dom.minidom.parseString(data)
+        root = xml_dom.documentElement
+
+        # Extract the title
+        foo = getElementByName(getElementByName(root, 'Service'), 'Title')
+        if foo:
+            self.title = foo.childNodes[0].data
+        
+        # Extract the abstract
+        foo = getElementByName(getElementByName(root, 'Service'), 'Abstract')
+        if foo and len(foo.childNodes[0].data):
+            self.abstract = foo.childNodes[0].data
+        
+        # Extract fees information
+        foo = getElementByName(getElementByName(root, 'Service'), 'Fees')
+        if foo and len(foo.childNodes[0].data) \
+               and foo.childNodes[0].data.lower() != 'none':
+            self.fees = foo.childNodes[0].data
+        
+        # Extract access information
+        foo = getElementByName(getElementByName(root, 'Service'),
+                               'AccessConstraints')
+        if foo and len(foo.childNodes[0].data) \
+               and foo.childNodes[0].data.lower() != 'none':
+            self.access = foo.childNodes[0].data
+        
+        foo = getElementByName(getElementByName(
+            root, 'Capability'), 'Request')
+
+        # Need to distinguish between Map and GetMap for v1.0 and v1.1
+        bar = getElementByName(foo, 'GetMap')
+        if bar:
+            # WMS 1.1
+            foo = getElementsByName(bar, 'Format')
+            self.formats = map((lambda i: i.childNodes[0].data), foo)
+        else:
+            # WMS 1.0
+            foo = getElementByName(getElementByName(
+                foo, 'Map'), 'Format')
+            for node in foo.childNodes:
+                if node.nodeType == Node.ELEMENT_NODE:
+                    try:
+                        self.formats.append(node.nodeName)
+                    except AttributeError:
+                        self.formats = [node.nodeName]
+
+        # Extract layer names
+        self.layers = []
+        self.peekLayers(getElementByName(getElementByName(
+            root, 'Capability'), 'Layer'), -1)
+
+        xml_dom.unlink()
+
+
+    def peekLayers(self, top, parent):
+        """
+        Inspect the provided DOM fragment referenced as top.
+
+        This method will inspect all included layers and traverse the
+        tree recursively in order to fill the internal datastructure.
+
+        Note that SRS other than EPSG:* are not yet supported,
+        especially there is no support for AUTO and NONE.
+        """
+
+        index = len (self.layers)
+        self.layers.append({})
+        self.layers[index]['parent'] = parent
+
+        for foo in top.attributes.keys():
+            if foo == 'queryable':
+                self.layers[index]['queryable'] \
+                    = int(top.attributes.get(foo).nodeValue)
+
+        foo = getElementByName(top, 'Title')
+        if foo and len(foo.childNodes[0].data):
+            self.layers[index]['title'] = foo.childNodes[0].data
+        else:
+            # A <Title> is required for each layer, <name> is optional
+            # See OGC 01-068r3, 7.1.4.5.1 and 7.1.4.5.2
+            self.error.append(_("No title found for layer #%d") % index)
+
+        foo = getElementByName(top, 'Name')
+        if foo and len(foo.childNodes[0].data):
+            self.layers[index]['name'] = foo.childNodes[0].data
+
+        # These values are only used for an integrity check
+        for foo in getElementsByName(top, 'SRS'):
+            for srs in foo.childNodes[0].data.split(" "):
+                if srs[0:5] == 'EPSG:':
+                    srs = srs[5:]
+                try:
+                    int(srs)
+                    try:
+                        self.layers[index]['srs'].append(srs)
+                    except KeyError:
+                        self.layers[index]['srs'] = [srs]
+                except ValueError:
+                    if srs[0:4].upper() == 'AUTO' \
+                           or srs[0:4].upper() == 'NONE':
+                        try:
+                            self.layers[index]['_srs_'].append(srs)
+                        except KeyError:
+                            self.layers[index]['_srs_'] = [srs]
+                    else:
+                        self.error.append(_("SRS '%s' is not numerical and not"
+                                            " AUTO/NONE in layer '%s'") \
+                                          % (srs, self.layers[index]['title']))
+
+        foo = getElementByName(top, 'LatLonBoundingBox')
+        if foo is not None:
+            self.layers[index]['llbbox'] = {}
+            for corner in ['minx', 'miny', 'maxx', 'maxy']:
+                self.layers[index]['llbbox'][corner] \
+                    = foo.attributes.get(corner).nodeValue
+
+        boxes = getElementsByName(top, 'BoundingBox')
+        if boxes != []:
+            self.layers[index]['bbox'] = {}
+        for foo in boxes:
+            srs = foo.attributes.get('SRS').nodeValue
+            if srs[0:5] == 'EPSG:':
+                srs = srs[5:]
+            self.layers[index]['bbox'][srs] = {}
+            for corner in ['minx', 'miny', 'maxx', 'maxy']:
+                self.layers[index]['bbox'][srs][corner] \
+                    = foo.attributes.get(corner).nodeValue
+            
+        # Traverse subsidiary layers
+        sublayer = getElementsByName(top, 'Layer')
+        for l in sublayer:
+            self.peekLayers(l, index)
+
+
+    def getTitle(self):
+        """
+        Returns the main title of the WMS object.
+
+        If no title is provided in the capabilities, an empty string
+        is returned.
+        """
+        if self.title is None:
+            return ''
+        else:
+            return self.title
+
+
+    def getAbstract(self):
+        """
+        Returns the abstract of the WMS object.
+
+        If no abstract is provided in the capabilities, an empty
+        string is returned.
+        """
+        if self.abstract is None:
+            return ''
+        else:
+            return self.abstract
+
+
+    def getFees(self):
+        """
+        Returns the fees information of the WMS object.
+
+        If no information is provided in the capabilities or if it is
+        set to 'none', an empty string is returned.
+        """
+        if self.fees is None:
+            return ''
+        else:
+            return self.fees
+
+
+    def getAccessConstraints(self):
+        """
+        Returns information about access constraints for the WMS object.
+
+        If no information is provided in the capabilities or if it is
+        set to 'none', an empty string is returned.
+        """
+        if self.access is None:
+            return ''
+        else:
+            return self.access
+
+
+    def getFormats(self):
+        """
+        Returns a list of supported output formats.
+
+        These are used in the GetMap request.  This method will
+        default to 'image/jpeg' if no format is recognised in XML
+        Capabilities, assuming that JPEG will always be supported on
+        the server side.
+        """
+        if self.formats is None:
+            return ['image/jpeg']
+        else:
+            return self.formats
+
+    def getLayers(self):
+        """
+        Returns a list of layer names.
+
+        Only named layers will be returned, since a layer may have a
+        title but doesn't have to have a name associated to it as
+        well.  If no layers were found, an empty list is returned.
+        """
+        result = []
+        for layer in self.layers:
+            if 'name' in layer:
+                result.append(layer['name'])
+
+        return result
+
+
+    def getSRS(self):
+        """
+        Returns the root list of spatial reference systems (SRS).
+
+        This list is taken from the root layer.  Those SRS are common
+        to all subsidiary layers.  If no SRS are common to all layers,
+        an empty list is returned.  If no layers were detected, an
+        empty list is returned as well.
+        """
+        if len(self.layers) == 0:
+            return []
+
+        # index 0 denotes the root layer by design
+        if 'srs' in self.layers[0].keys():
+            return self.layers[0]['srs']
+
+
+    def getLayerTitle(self, name):
+        """
+        Returns the title of the named layer.
+
+        If no such title or no such layer exists, an empty string is
+        returned.
+        """
+        for layer in self.layers:
+            if 'name' in layer:
+                if layer['name'] == name:
+                    if 'title' in layer:
+                        return layer['title']
+
+        return ''
+
+
+    def getLayerSRS(self, name):
+        """
+        Returns a list of spacial reference systems (SRS).
+
+        The SRS are specified by the European Petroleum Survey Group
+        (EPSG).  There should be at least one SRS per layer, though.
+        The prefix 'EPSG:' will be stripped.  If none exists, an empty
+        list is returned.
+
+        The specification [OGC 01-068r3] says about inheritance of
+        SRS:
+
+        - Every layer is available in one or more SRS (or in an
+          undefined SRS)
+
+        - Geographic information whose SRS is undefined
+          (e.g. digitised historical maps) shall use 'NONE'
+          (case-sensitive).  This implementation does not support
+          this.
+
+        - Every layer shall have at least one SRS element that is
+          either stated explicitly or inherited from a parent layer.
+
+        - The root layer element shall include a sequence of zero or
+          more SRS elements listing all SRS which are common for to
+          all subsidiary layers.
+
+        - Layers may optionally add to the global SRS list, or to the
+          list inherited from a parent layer.
+
+        - A server which has the ability to transform data to
+          different SRSes may choose not to provide an explicit
+          BoundingBox for every possible SRS available for each Layer.
+          Thus the list of <SRS> elements are authoritative.
+
+        This implementation returns the list of SRS for the given
+        layer, calculated by looking at BoundingBoxes defined in the
+        named layer and all layers higher in the hierarchy up to the
+        root layer which weren't overwritten.
+        """
+        for i in range(len(self.layers)):
+            if 'name' in self.layers[i]:
+                if self.layers[i]['name'] == name:
+                    pivot = i
+                    break
+        else:
+            return []
+
+        result = []
+        while pivot != -1:
+            if 'srs' in self.layers[pivot]:
+                for srs in self.layers[pivot]['srs']:
+                    if srs not in result:
+                        result.append(srs)
+            pivot = self.layers[pivot]['parent']
+
+        return result
+
+
+    def getLayerLatLonBBox(self, name):
+        """
+        Returns a dictionary of the LatLonBoundingBox.
+
+        ... for the named layer if it exists.  The SRS is always
+        EPSG:4326 per convention.  There should be at least one,
+        though, inherited from the root layer at least.  If none
+        exists, the value None is returned.
+        """
+        for layer in self.layers:
+            if 'name' in layer:
+                if layer['name'] == name:
+                    if 'llbbox' in layer:
+                        return layer['llbbox']
+                    else:
+                        # No LatLonBoundingBox found in current layer,
+                        # so traverse the hierarchy upwards and check
+                        # again until there is one.
+                        pivot = layer
+                        while pivot['parent'] != -1:
+                            pivot = self.layers[pivot['parent']]
+                            if 'llbbox' in pivot:
+                                return pivot['llbbox']
+
+        return None
+
+
+    def getLayerBBox(self, name, srs):
+        """
+        Returns a dictionary of the BoundingBox.
+
+        If no such BoundingBox exists, None is returned.
+
+        The specification [OGC 01-068r3] says about BoundingBoxes:
+
+        - Layers may have zero or more BoundingBox elements what are
+          either stated explicitly or inherited from a parent layer.
+
+        - A layer may have multiple BoundingBox elements, but each one
+          shall state a different SRS.
+
+        - A layer inherits any BoundingBoxes defined by its
+          parents.
+
+        - A BoundingBox inherited from the parent layer for a
+          particular SRS is replaced by any declaration for the same
+          SRS in the current layer.
+
+        - A BoundingBox in the child layer for a new SRS which is not
+          already declared by the parent, is added to the list of
+          BoundingBoxes for the child layer.
+
+        - A single layer shall not contain more than one BoundingBox
+          element for the same SRS.
+        """
+        for layer in self.layers:
+            if 'name' in layer:
+                if layer['name'] == name:
+                    if 'bbox' in layer:
+                        if srs in layer['bbox']:
+                            return layer['bbox'][srs]
+                    
+                    # No BoundingBox for the given SRS found in
+                    # current layer, so traverse the hierarchy upwards
+                    # and check again until there is one.
+                    pivot = layer
+                    while pivot['parent'] != -1:
+                        pivot = self.layers[pivot['parent']]
+                        if 'bbox' in pivot:
+                            if srs in pivot['bbox']:
+                                return pivot['bbox'][srs]
+
+        # No matching BBox found, let's see if it was EPSG:4326
+        if srs == '4326':
+            return self.getLayerLatLonBBox(name)
+
+        return None
+
+
+    def isQueryable(self, name):
+        """
+        Returns the value of the queryable attribute of a layer.
+
+        This attribute denotes whether this layer can be queried
+        through the GetFeatureInfo request.  The default value is 0.
+
+        The specification [OGC 01-068r3] this attribute can be
+        inherited.
+        """
+
+        for layer in self.layers:
+            if 'name' in layer:
+                if layer['name'] == name:
+                    try:
+                        return layer['queryable']
+                    except KeyError:
+                        # No attribute in this layer, so traverse the
+                        # hierarchy upwards
+                        pivot = layer
+                        while pivot['parent'] != -1:
+                            pivot = self.layers[pivot['parent']]
+                            if 'queryable' in pivot:
+                                return pivot['queryable']
+        return 0
+
+
+
+if __name__ == "__main__":
+    print "This module cannot be executed standalone."
+
+    import os
+
+    sample = "test/sample.xml"
+    try:
+        f = open(sample, "r")
+    except IOError:
+        try:
+            f = open(os.path.dirname(__file__) + "/" + sample, "r")
+        except IOError:
+            print "Cannot open %s for reading" % sample
+
+    if f is not None:
+        sample = f.read();
+        f.close()
+        
+        ina = WMSCapabilitiesParser()
+        ina.grok(sample)

Added: packages/thuban/branches/upstream/current/Extensions/wms/properties.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/properties.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/properties.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,192 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Edit Layer Properties
+
+class wmsProperties(NonModalNonParentDialog):
+    __init__
+
+    dialog_layout(text)
+
+    OnOK(event)
+    OnCancel(event)
+
+Problems:
+
+    1. The wxTextCtrl should fit to the right side of the horizontal
+       box/sizer.  It doesn't.  I only found the sizer.Add() method to
+       be able to take proportions but no way to tell the object to
+       fill all remaining space.
+
+    2. The framed box "Layers" needs to be scrollable if there are
+       more than 12 items, since the dialog would probably not fit on
+       people's screen anymore.
+
+       Todo: This can be solved (in C it was possible at least),
+       probably with wxScrolledWindow
+
+    3. The button hbox is not aligned to the right side which should
+       be.  For some reason wxALIGN_RIGHT does not have any effect.
+       Maybe I just misunderstood the documentation?
+
+"""
+
+__version__ = "$Revision: 2440 $"
+# $Source$
+# $Id: properties.py 2440 2004-12-09 10:39:43Z joey $
+
+from Thuban import _
+from Thuban.UI.dialogs import NonModalNonParentDialog
+
+from wxPython.wx import *
+#    wxBoxSizer, wxVERTICAL, wxHORIZONTAL, \
+#    wxButton, wxID_OK, wxID_CANCEL, wxALL, wxALIGN_CENTER_HORIZONTAL, \
+#    EVT_BUTTON, wxEXPAND, wxStaticBoxSizer, wxStaticBox, wxALIGN_RIGHT, \
+#    wxALIGN_BOTTOM
+
+ID_WMS_TITLE   = 5001
+ID_WMS_LAYER   = 5002
+ID_WMS_FORMATS = 5003
+
+MAX_LAYERNAME_LENGTH = 45
+MAX_VISIBLE_LAYERS   = 12
+
+class wmsProperties(NonModalNonParentDialog):
+    """
+    Representation for the WMS properties dialog
+    """
+
+    def __init__(self, parent, name, layer, *args, **kw):
+        """
+        Build the properties dialog
+        """
+        title = _("Edit WMS Properties")
+        NonModalNonParentDialog.__init__(self, parent, name, title)
+
+        self.layer = layer
+
+        # Hooks for the widgets to get user data
+        self.entry = None
+        self.layers = {}
+        self.formats = None
+
+        self.dialog_layout(layer)
+
+
+    def dialog_layout(self, layer):
+        """
+        Set up the information dialog
+        """
+
+        # main box for the entire dialog
+        mainbox = wxBoxSizer(wxHORIZONTAL)
+        
+        # vertical box to contain the three parts
+        #     (title, layers, formats+buttons)
+        vbox = wxBoxSizer(wxVERTICAL)
+        mainbox.Add(vbox, 0, wxALL|wxEXPAND, 4)
+        
+        # edit the title
+        hbox = wxBoxSizer(wxHORIZONTAL)
+        vbox.Add(hbox, 0, wxALL, 0)
+        label = wxStaticText(self, ID_WMS_TITLE, _("Title:"))
+        hbox.Add(label, 1, wxALL|wxEXPAND, 4)
+        self.entry = wxTextCtrl(self, ID_WMS_TITLE, layer.Title())
+        hbox.Add(self.entry, 7, wxALL|wxEXPAND|wxALIGN_RIGHT, 0)
+
+        layerbox = wxStaticBox(self, ID_WMS_LAYER, _("Layers"))
+        lbox = wxStaticBoxSizer(layerbox, wxVERTICAL)
+        vbox.Add(lbox, 0, wxALL, 0)
+        visible = layer.getVisibleLayers()
+        for l in layer.getLayers():
+            checker = wxCheckBox(self, ID_WMS_LAYER, layer.getLayerTitle(l)[0:MAX_LAYERNAME_LENGTH].encode('latin1'))
+            self.layers[l] = checker
+            if l in visible:
+                checker.SetValue(True)
+            lbox.Add(checker, 0, wxALL|wxEXPAND, 0)
+
+        # tiled box:
+        hbox = wxBoxSizer(wxHORIZONTAL)
+        vbox.Add(hbox, 0, wxALL|wxEXPAND, 0)
+        
+        # left part: image format selection
+        formatbox = wxBoxSizer(wxHORIZONTAL)
+        hbox.Add(formatbox, 1, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 0)
+        label = wxStaticText(self, ID_WMS_FORMATS, _("Format:"))
+        formatbox.Add(label, 0, wxALL|wxALIGN_CENTER_VERTICAL, 4)
+        self.formats = wxChoice(self, ID_WMS_FORMATS)
+        formatbox.Add(self.formats, 1, wxALL|wxEXPAND|wxALIGN_CENTER_VERTICAL, 4)
+
+        # fill the select box
+        match = 0
+        count = 0
+        format = layer.getWMSFormat()
+        for f in layer.getFormats():
+            self.formats.Append(f)
+            if f == format:
+                match = count
+            count += 1
+
+        self.formats.Fit()
+        self.formats.SetSelection(match)
+
+        # Build the button hbox, to be added into row
+        buttons = wxBoxSizer(wxHORIZONTAL)
+        hbox.Add(buttons, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 0)
+        buttons.Add(wxButton(self, wxID_OK, _("OK")), 0, wxALL, 4)
+        buttons.Add(wxButton(self, wxID_CANCEL, _("Cancel")), 0, wxALL, 4)
+        EVT_BUTTON(self, wxID_OK, self.OnOK)
+        EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(mainbox)
+        mainbox.Fit(self)
+        mainbox.SetSizeHints(self)
+
+
+    def OnOK(self, event):
+        """
+        Handle the 'OK button pressed' event
+
+        i.e. transfer user input into the layer
+        """
+
+        # Set the title
+        self.layer.SetTitle(self.entry.GetValue())
+
+        # Set the image format for WMS GetMap requests
+        selection = self.formats.GetSelection()
+        if selection > -1:
+            self.layer.setWMSFormat(self.formats.GetString(self.formats.GetSelection()))
+
+        # Set the list of visible layers
+        visible = []
+        for l in self.layers.keys():
+            if self.layers[l].IsChecked():
+                visible.append(l)
+        self.layer.setVisibleLayers(visible)
+
+        self.Close()
+
+
+    def OnCancel(self, event):
+        """
+        Handle the 'Cancel button pressed' event
+        """
+        self.Close()

Added: packages/thuban/branches/upstream/current/Extensions/wms/test/adjustpath.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/test/adjustpath.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/test/adjustpath.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,40 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Add the main Thuban directory to the path, so that Thuban modules can
+be added without problems.
+
+Exported variables:
+
+thubandir -- absolute path to the main Thuban directory
+
+"""
+
+__version__ = "$Revision: 2117 $"
+# $Source$
+# $Id: adjustpath.py 2117 2004-03-19 17:00:17Z joey $
+
+import os
+from sys import path
+
+if os.path.dirname(__file__) == "" or os.path.dirname(__file__) == ".":
+    thubandir = os.path.abspath("../../..")
+else:
+    thubandir = os.path.abspath(os.path.dirname(__file__) + "/../../..")
+path.insert(0, thubandir)

Added: packages/thuban/branches/upstream/current/Extensions/wms/test/test_domutils.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/test/test_domutils.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/test/test_domutils.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,171 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Test for the domutils module
+
+"""
+
+__version__ = "$Revision: 2122 $"
+# $Source$
+# $Id: test_domutils.py 2122 2004-03-24 11:47:31Z joey $
+
+import unittest
+import xml.dom.minidom
+
+import adjustpath
+
+from Extensions.wms.domutils import getElementByName, getElementsByName
+
+
+class TestDOMutils(unittest.TestCase):
+    """
+    Defines a test environment for the class WMSCapabilities.
+    """
+
+    root = None
+
+    def setUp(self):
+        """
+        Set up the XML test string, parse it into a DOM element and
+        hook it to the internal root variable.
+        """
+        data = "\n".join(['<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>',
+                          '<!DOCTYPE WMT_MS_Capabilities SYSTEM "http://www.digitalearth.gov/wmt/xml/capabilities_1_0_8.dtd">',
+                          '<WMT_MS_Capabilities version="1.0.8" updateSequence="0">',
+                          '  <Layer>',
+                          '    <Name>Osnabrueck</Name>',
+                          '    <Layer>',
+                          '      <Name>gewaesser</Name>',
+                          '      <Layer queryable="0" opaque="0" cascaded="0">',
+                          '        <Name>gewaesserpolyl</Name>',
+                          '      </Layer>',
+                          '    </Layer>',
+                          '    <Layer queryable="0" opaque="0" cascaded="0">',
+                          '      <Name>gruenflaechen</Name>',
+                          '    </Layer>',
+                          '  </Layer>',
+                          '</WMT_MS_Capabilities>'])
+        self.root = xml.dom.minidom.parseString(data).documentElement
+
+
+    def compareLists(self, foo, bar):
+        """
+        Compare two lists
+        - check same number of elements
+        - check whether all elements in the first list are part of the second
+        """
+
+        # Check for same number of elements
+        if len(foo) != len(bar):
+            self.fail("Different number of elements");
+
+        # Loop through all elements for existance
+        for elm in foo:
+            if elm not in bar:
+                self.fail("%s not in second list" % elm);
+
+
+    def compareNodeLists (self, result, nodelist):
+        """
+        Compares the Name children versus the given result list.
+        """
+
+        names = []
+        for pivot in nodelist:
+            for i in range (pivot.childNodes.length):
+                if pivot.childNodes[i].nodeName == 'Name':
+                    names.append(pivot.childNodes[i].childNodes[0].data)
+
+        self.compareLists(result, names)
+
+
+    def compareNode (self, result, node):
+        """
+        Compares the Name child versus the given result.
+        """
+
+        for i in range (node.childNodes.length):
+            if node.childNodes[i].nodeName == 'Name':
+                self.assertEquals(result, node.childNodes[i].childNodes[0].data)
+                break
+        else:
+            self.fail("No Name child found.");
+
+
+    def test_compareLists (self):
+        """
+        Test the internal compareLists function.
+        """
+
+        # Zero element
+        self.compareLists([], [])
+
+        # Single element
+        self.compareLists(['alpha'], ['alpha'])
+
+        # Multiple elements
+        self.compareLists(['alpha', 'beta', 'gamma'], ['alpha', 'beta', 'gamma'])
+
+        # Multiple elements, different order
+        self.compareLists(['alpha', 'beta', 'gamma'], ['gamma', 'alpha', 'beta'])
+
+
+    def test_getElementsByName (self):
+        """
+        Test for the getElementsByName function.
+        """
+
+        # Test for level 1
+        result = ['Osnabrueck']
+        self.compareNodeLists(result, getElementsByName(self.root, 'Layer'))
+
+        # Test for level 2
+        result = ['gruenflaechen', 'gewaesser']
+        self.compareNodeLists(result, getElementsByName(getElementsByName(self.root, 'Layer')[0], 'Layer'))
+
+        # Test for level 3
+        result = ['gewaesserpolyl']
+        self.compareNodeLists(result,
+                              getElementsByName
+                              (getElementsByName
+                               (getElementsByName
+                                (self.root, 'Layer')[0], 'Layer')[0], 'Layer'))
+
+
+    def test_getElementByName (self):
+        """
+        Test for the getElementByName function.
+        """
+
+        # Test for level 1
+        self.compareNode('Osnabrueck', getElementByName(self.root, 'Layer'))
+
+        # Test for level 2
+        self.compareNode('gewaesser', getElementByName(getElementByName(self.root, 'Layer'), 'Layer'))
+
+        # Test for level 3
+        self.compareNode('gewaesserpolyl',
+                         getElementByName
+                         (getElementByName
+                          (getElementByName
+                           (self.root, 'Layer'), 'Layer'), 'Layer'))
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/Extensions/wms/test/test_ogclib.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/test/test_ogclib.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/test/test_ogclib.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,262 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test for the PyOGCLib from Sean C. Gillies <sgillies at users.sourceforge.net>
+
+http://www.sourceforge.net/projects/pyogclib
+
+Requires the ogclib installed regularily on the system, accessible via
+PYTHONPATH or checked out alongside the Thuban checkout.
+"""
+
+__version__ = "$Revision: 2430 $"
+# $Source$
+# $Id: test_ogclib.py 2430 2004-11-30 16:59:01Z joey $
+
+import os
+import unittest
+
+from string import split
+from sys import path
+
+from adjustpath import thubandir
+path.insert(0, thubandir + "/test")
+
+import support
+
+# ----------------------------------------------------------------------
+# FIXME: Temporary code until PyOGCLib is a standard requirement
+
+from sys import path
+
+# Assume the PyOGCLib to be checked out next to the thuban main directory
+# setting PYTHONPATH accordingly is fine as well
+#
+pyogclib = os.path.abspath(thubandir + "/../PyOGCLib")
+if os.path.isdir(pyogclib) and os.path.isdir(pyogclib + "/ogclib"):
+    path.insert(0, pyogclib)
+# ----------------------------------------------------------------------
+
+_pyogclib_import_error = None
+try:
+    from ogclib.WMSClient import WMSClient
+except ImportError, extra:
+    _pyogclib_import_error = str(extra)
+
+
+class TestOGCLib(unittest.TestCase):
+    """
+    Defines a test environment for the PyOGCLib, i.e. check whether URL
+    strings are built properly.
+    """
+
+    wmsclient = None
+
+    def setUp(self):
+        skip_if_no_ogclib()
+        self.wmsclient = WMSClient()
+
+    def compare_URLs(self, foo, bar):
+        """
+        Check if two URLs are equal, i.e.:
+        - check for same base URL
+        - check same number of HTTP GET arguments
+        - check whether all arguments from one URL also exist in the second
+        """
+
+        foo_tuple = split(foo, "?")
+        bar_tuple = split(bar, "?")
+
+        # Check for same base URL
+        if foo_tuple[0] != bar_tuple[0]:
+            self.fail("%s != %s" %(foo_tuple[0], bar_tuple[0]))
+
+        # Check for same length of entire HTTP GET argument string
+        if len(foo_tuple) != len(bar_tuple):
+            self.fail("One URL has no arguments");
+
+        # Loop through all HTTP GET arguments for existance
+        if len(foo_tuple) > 1 and len(bar_tuple) > 1:
+            foo_opts = split(foo_tuple[1], "&")
+            bar_opts = split(bar_tuple[1], "&")
+
+            if len(foo_opts) != len(bar_opts):
+                self.fail("Different number of arguments");
+
+            for part in foo_opts:
+                if part not in bar_opts:
+                    self.fail("%s not in second argument list" % part);
+
+
+    def test_compareURLs(self):
+        """Perform some tests for own compare routine"""
+
+        # Compare same base URL
+        result = "http://frida.intevation.org/cgi-bin"
+        self.compare_URLs("http://frida.intevation.org/cgi-bin", result)
+
+        # Compare different base URL with same length
+        self.assertRaises(AssertionError, self.compare_URLs, "http://frida.intevation.org/cgi-lib", result)
+
+        # Compare same bse with one argument
+        result = "http://frida.intevation.org/cgi-bin?foo=eins"
+        self.compare_URLs("http://frida.intevation.org/cgi-bin?foo=eins", result)
+
+        # Compare same base URL differnt first argument
+        self.assertRaises(AssertionError, self.compare_URLs, "http://frida.intevation.org/cgi-bin?bar=eins", result)
+
+        # Compare same base with two arguments
+        result = "http://frida.intevation.org/cgi-bin?foo=eins&bar=zwei"
+        self.compare_URLs("http://frida.intevation.org/cgi-bin?foo=eins&bar=zwei", result)
+        self.compare_URLs("http://frida.intevation.org/cgi-bin?bar=zwei&foo=eins", result)
+
+        # Compare same base with different two arguments
+        self.assertRaises(AssertionError, self.compare_URLs, "http://frida.intevation.org/cgi-bin?foo=zwei&bar=eins", result)
+
+        # Compare same base with three arguments
+        result = "http://frida.intevation.org/cgi-bin?foo=eins&bar=zwei&baz=jan&quux=tux"
+        self.compare_URLs("http://frida.intevation.org/cgi-bin?foo=eins&bar=zwei&baz=jan&quux=tux", result)
+        self.compare_URLs("http://frida.intevation.org/cgi-bin?baz=jan&bar=zwei&quux=tux&foo=eins", result)
+
+        # Compare same base with different three arguments
+        testurl = "http://frida.intevation.org/cgi-bin?baz=jan&foo=zwei&quux=tux&bar=eins"
+        self.assertRaises(AssertionError, self.compare_URLs, testurl, result)
+
+
+    def test_CapabilityURL(self):
+        """Test the getCapabilitiesURL() method"""
+
+        frida = "http://frida.intevation.org/cgi-bin/frida_wms?"
+
+        url = self.wmsclient.getCapabilitiesURL(frida, "1.0")
+        result = frida + "WMTVER=1.0&REQUEST=capabilities"
+        self.compare_URLs(url, result)
+
+        url = self.wmsclient.getCapabilitiesURL(frida, "1.1")
+        result = frida + "VERSION=1.1&SERVICE=WMS&REQUEST=GetCapabilities"
+        self.compare_URLs(url, result)
+
+
+    def test_GetMapURL(self):
+        """Test the getMapURL() method"""
+
+        frida = "http://frida.intevation.org/cgi-bin/frida_wms?"
+
+        format = 'image/jpeg'
+        format_enc = 'image%2Fjpeg'
+        width = 400
+        height = 350
+        epsg = 4326
+        bbox = {'minx': -107, 'miny': 40, 'maxx': -109, 'maxy': 41}
+        layers = [ ]
+        styles = [ ]
+        version = '1.1'
+
+        result_base = frida + "WMTVER=1.0&REQUEST=map" + \
+                      "&FORMAT="+format_enc + \
+                      "&SRS=EPSG%s%d" %("%3A", epsg) + \
+                      "&BBOX=%f%s%f%s%f%s%f" %(bbox['minx'], "%2C", bbox['miny'], "%2C",
+                                                bbox['maxx'], "%2C", bbox['maxy']) + \
+                                                "&WIDTH=%s" % width + "&HEIGHT=%s" % height
+        result = result_base + \
+                 "&LAYERS=" + "%2C".join(layers) + \
+                 "&STYLES=" + "%2C".join(styles)
+        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
+                             bbox, layers, version=version)
+
+        # Repeat and continue with version 1.1, as denoted in OGC 01-068r3
+        version = '1.1'
+        result_base = frida + "VERSION=1.1&SERVICE=WMS&REQUEST=GetMap" + \
+                      "&FORMAT="+format_enc + \
+                      "&SRS=EPSG%s%d" %("%3A", epsg) + \
+                      "&BBOX=%f%s%f%s%f%s%f" %(bbox['minx'], "%2C", bbox['miny'], "%2C",
+                                                bbox['maxx'], "%2C", bbox['maxy']) + \
+                                                "&WIDTH=%s" % width + "&HEIGHT=%s" % height
+        result = result_base + \
+                 "&LAYERS=" + "%2C".join(layers) + \
+                 "&STYLES=" + "%2C".join(styles)
+        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
+                             bbox, layers, version=version)
+        self.compare_URLs(result, url)
+
+        result += "&TRANSPARENT=TRUE"
+        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
+                             bbox, layers, version=version,
+                             transparent=1 )
+        self.compare_URLs(result, url)
+
+        result += "&BGCOLOR=0xFF00FF"
+        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
+                             bbox, layers, version=version,
+                             transparent=1, bgcolor='0xFF00FF')
+        self.compare_URLs(result, url)
+
+        layers = [ 'foo' ]
+        result = result_base + \
+                 "&LAYERS=" + "%2C".join(layers) + \
+                 "&STYLES=" + "%2C".join(styles)
+        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
+                             bbox, layers, version=version)
+        self.compare_URLs(result, url)
+
+        layers.append('bar')
+        result = result_base + \
+                 "&LAYERS=" + "%2C".join(layers) + \
+                 "&STYLES=" + "%2C".join(styles)
+        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
+                             bbox, layers, version=version)
+        self.compare_URLs(result, url)
+
+        styles = [ 'something' ]
+        result = result_base + \
+                 "&LAYERS=" + "%2C".join(layers) + \
+                 "&STYLES=" + "%2C".join(styles)
+        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
+                             bbox, layers, version=version,
+                             styles = styles)
+        self.compare_URLs(result, url)
+
+        styles.append('else')
+        result = result_base + \
+                 "&LAYERS=" + "%2C".join(layers) + \
+                 "&STYLES=" + "%2C".join(styles)
+        url = self.wmsclient.getMapURL(frida, format, width, height, epsg,
+                             bbox, layers, version=version,
+                             styles = styles)
+        self.compare_URLs(result, url)
+
+
+def skip_if_no_ogclib():
+    if _pyogclib_import_error is not None:
+        raise support.SkipTest(_pyogclib_import_error)
+#        raise support.SkipTest("No PyOGCLib found, hence no tests available.")
+
+
+if __name__ == "__main__":
+    support.run_tests()
+
+"""
+
+Additional notes:
+    - Parameter names shall not be case sensitive, but parameter
+      values shall be case sensitive. [OGC 01-068r3, 6.4.1, p13]
+
+      This is not supported by the compare URL method, but may need to
+      in the future.
+
+    - Some geospatial inforamtion may be available at multiple times,
+      like a whether map or satalite photo.  Capabilities may announce
+      available times. [OGC 01-068r3, 6.5.7, p18]
+
+      This is not yet supported by WMSClient
+
+    - According to the specs a comma in LAYERS and STYLES list doesn't
+      have to be encoded.  Maybe this could cause problems with some
+      servers, just to keep in mind.
+
+"""

Added: packages/thuban/branches/upstream/current/Extensions/wms/test/test_parser.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/test/test_parser.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/test/test_parser.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,319 @@
+# -*- encoding: iso-8859-1 -*-
+#
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Test for WMSCapabilitiesParser from ../parser.py
+
+"""
+
+__version__ = "$Revision: 2382 $"
+# $Source$
+# $Id: test_parser.py 2382 2004-10-04 17:03:29Z joey $
+
+import os
+import unittest
+
+import adjustpath
+
+from Extensions.wms.parser import WMSCapabilitiesParser
+
+
+class TestWMSCapabilitiesParser(unittest.TestCase, WMSCapabilitiesParser):
+    """
+    Defines a test environment for the class WMSCapabilities.
+    """
+
+    def compareLists(self, foo, bar):
+        """
+        Compare two lists
+        - check same number of elements
+        - check whether all elements in the first list are part of the second
+        """
+
+        # Check for same number of elements
+        if len(foo) != len(bar):
+            self.fail("Different number of elements");
+
+        # Loop through all elements for existance
+        for elm in foo:
+            if elm not in bar:
+                self.fail("%s not in second list" % elm);
+
+
+    def compareDicts(self, foo, bar):
+        """
+        Compare two dictionaries (hashes)
+        - check same number of keys
+        - check whether all keys from the first list are part of the second
+        """
+
+        # Check for same number of elements
+        if len(foo) != len(bar):
+            self.fail("Different number of keys");
+
+        # Loop through all elements for existance
+        for key in foo.keys():
+            if key not in bar:
+                self.fail("%s not in second dictionary" % key);
+            if foo[key] != bar[key]:
+                self.fail("%s has different value in second dictionary" % key);
+
+
+    def setUp(self):
+        """
+        Load the locally stored frida capabilities.
+        http://frida.intevation.org/cgi-bin/frida_wms?
+        """
+
+        try:
+            try:
+                f = open("sample.xml", "r")
+            except:
+                f = open(os.path.dirname(__file__) + "/sample.xml", "r")
+        except:
+            print "Cannot open sample.xml for reading"
+        else:
+            xml = f.read();
+            f.close()
+            self.grok(xml)
+
+
+    def test_compareLists(self):
+        """
+        Test the internal compareLists method.
+        """
+
+        # Equality of empty lists
+        self.compareLists([], [])
+
+        # Equality of equal lists
+        self.compareLists([1,2], [1,2])
+
+        # Equality of permuted lists
+        self.compareLists([1,2], [2,1])
+
+        # Equality of large permuted lists
+        self.compareLists([1,2,3,4,5,6,7,8], [8,3,1,2,5,7,4,6])
+
+        # Non-Equality of different lists
+        self.assertRaises(AssertionError, self.compareLists, [1,2], [3,2])
+
+        # Non-Equality of different lists
+        self.assertRaises(AssertionError, self.compareLists, [1,2], [3,2,1])
+
+        # Non-Equality of empty and non-empty list
+        self.assertRaises(AssertionError, self.compareLists, [], [3,2,1])
+        
+
+    def test_compareDicts(self):
+        """
+        Test the internal compareDicts method.
+        """
+
+        # Equality of empty dictionaries
+        self.compareDicts({}, {})
+
+        # Equality of equal dictionaries
+        # Python may represent the dictionaries differently
+        self.compareDicts({10:20, 11:30}, {10:20, 11:30})
+                        
+        # Equality of permuted dictionaries
+        # Python may represent the dictionaries similar anyway
+        self.compareDicts({10:20, 11:30}, {11:30, 10:20})
+                        
+        # Non-equality of different dictionaries
+        self.assertRaises(AssertionError, self.compareDicts, {10:20, 11:30},
+                          {10:20, 11:30, 12:40})
+
+        # Non-equality of empty and non-empty dictionaries
+        self.assertRaises(AssertionError, self.compareDicts, {},
+                          {10:20, 11:30, 12:40})
+
+
+    def test_general(self):
+        """
+        Test general attributes extracted from Capabilities XML
+        """
+
+        self.assertEquals(self.getTitle().encode('latin-1'),
+                          'Frida - Freie Vektor-Geodaten Osnabrück')
+        self.assertEquals(self.getAbstract(), '')
+        self.assertEquals(self.getFees(), '')
+        self.assertEquals(self.getAccessConstraints(), '')
+        formats = ['image/gif', 'image/png', 'image/jpeg', 'image/wbmp']
+        self.compareLists(self.getFormats(), formats)
+        layers = ['Osnabrueck', 'gruenflaechen', 'gewaesser',
+                  'gewaesserpolyl','gewaesserlinien', 'strassen_all',
+                  'strassenhinten', 'strassen', 'beschriftung',
+                  'hauptbeschriftung', 'sehenswuerdigkeiten']
+        self.compareLists(self.getLayers(), layers)
+        self.compareLists(self.getSRS(), ['31493'])
+
+
+    def test_LayerTitle(self):
+        """
+        Check if layer titles are recognised properly
+        """
+
+        # main layer
+        self.assertEquals(self.getLayerTitle('Osnabrueck').encode('latin-1'),
+                          'Frida - Freie Vektor-Geodaten Osnabrück')
+
+        # first nested layer
+        self.assertEquals(self.getLayerTitle(
+                          'gruenflaechen').encode('latin-1'),
+                          'Grünflächen')
+
+        # first nested layer
+        self.assertEquals(self.getLayerTitle('gewaesser').encode('latin-1'),
+                          'Gewässer')
+
+        # second nested layer
+        self.assertEquals(self.getLayerTitle(
+                          'gewaesserpolyl').encode('latin-1'),
+                          'Gewässerflächen')
+
+
+    def test_LayerSRS(self):
+        """
+        Check if the SRS are returned properly
+        """
+
+        # SRS of main layer
+        self.compareLists(self.getLayerSRS('Osnabrueck'), ['31493'])
+
+        # Single SRS of layer without inheritance
+        self.compareLists(self.getLayerSRS('gruenflaechen'), ['31493'])
+
+        # Multiple SRS of layer without inheritance, but overwriting
+        self.compareLists(self.getLayerSRS('gewaesserpolyl'),
+                          ['31493', '31494'])
+
+        # Multiple SRS of layer with inheritance, one new locally
+        self.compareLists(self.getLayerSRS('gewaesserlinien'),
+                          ['31493', '31492'])
+
+        # Multiple SRS with inheritance, two new locally
+        self.compareLists(self.getLayerSRS('strassen'),
+                          ['31493', '31494', '31495'])
+
+        # Single SRS with inheritance but overwriting
+        self.compareLists(self.getLayerSRS('beschriftung'),
+                          ['31493', '31494', '31495'])
+
+        # SRS of a layer with AUTO SRS ignored
+        self.compareLists(self.getLayerSRS('sehenswuerdigkeiten'), ['31493'])
+
+
+    def test_LatLonBoundingBoxes(self):
+        """
+        Check if the LatLonBoundingBoxes are returned properly
+        """
+
+        # main LatLonBoundingBox
+        bbox = {'minx': "7.92881", 'miny': "52.2131",
+                'maxx': "8.18349", 'maxy': "52.341"}
+        self.compareDicts(self.getLayerLatLonBBox('Osnabrueck'), bbox)
+
+        # inherited LatLonBoundingBox
+        bbox = {'minx': "7.92881", 'miny': "52.2131",
+                'maxx': "8.18349", 'maxy': "52.341"}
+        self.compareDicts(self.getLayerLatLonBBox('gewaesser'), bbox)
+
+        # third layer non-inherited LatLonBoundingBox
+        bbox = {'minx': "7.93531", 'miny': "52.2328",
+                'maxx': "8.17739", 'maxy': "52.3353"}
+        self.compareDicts(self.getLayerLatLonBBox('gewaesserpolyl'), bbox)
+
+
+    def test_BoundingBoxes(self):
+        """
+        Check if the BoundingBoxes are returned properly
+        """
+
+        # main BoundingBox
+        bbox = {'minx': "3.427e+06",  'miny': "5.787e+06",
+                'maxx': "3.4442e+06", 'maxy': "5.801e+06"}
+        self.compareDicts(self.getLayerBBox('Osnabrueck', '31493'), bbox)
+
+        # inherited BoundingBox
+        self.compareDicts(self.getLayerBBox('gewaesser', '31493'), bbox)
+
+        # overwritten BoundingBox
+        bbox = {'minx': "3.427e+06",   'miny': "5.78901e+06",
+                'maxx': "3.44173e+06", 'maxy': "5.79952e+06"}
+        self.compareDicts(self.getLayerBBox('gewaesserlinien', '31492'), bbox)
+
+        # multiple BoundingBoxes
+        bbox = {'minx': "3.42743e+06", 'miny': "5.78919e+06",
+                'maxx': "3.44381e+06", 'maxy': "5.80038e+06"}
+        self.compareDicts(self.getLayerBBox('gewaesserpolyl', '31493'), bbox)
+        bbox = {'minx': "3.42742e+06", 'miny': "5.78918e+06",
+                'maxx': "3.44380e+06", 'maxy': "5.80037e+06"}
+        self.compareDicts(self.getLayerBBox('gewaesserpolyl', '31494'), bbox)
+
+        # Non-existing BoundingBox
+        self.assertEquals(self.getLayerBBox('beschriftung', '31490'), None)
+
+
+    def test_LatLonBoundingBoxes_as_bboxes(self):
+        """
+        Check if the LatLonBoundingBoxes are returned properly
+        """
+
+        # main LatLonBoundingBox
+        bbox = {'minx': "7.92881", 'miny': "52.2131",
+                'maxx': "8.18349", 'maxy': "52.341"}
+        self.compareDicts(self.getLayerBBox('Osnabrueck', '4326'), bbox)
+
+        # inherited LatLonBoundingBox
+        bbox = {'minx': "7.92881", 'miny': "52.2131",
+                'maxx': "8.18349", 'maxy': "52.341"}
+        self.compareDicts(self.getLayerBBox('gewaesser', '4326'), bbox)
+
+        # third layer non-inherited LatLonBoundingBox
+        bbox = {'minx': "7.93531", 'miny': "52.2328",
+                'maxx': "8.17739", 'maxy': "52.3353"}
+        self.compareDicts(self.getLayerBBox('gewaesserpolyl', '4326'), bbox)
+
+
+    def test_queryable(self):
+        """
+        Check if layers are properly classified queryable or not
+        """
+
+        # implicit setting in main layer
+        self.assertEquals(self.isQueryable('Osnabrueck'), 0)
+
+        # explicit setting in second layer
+        self.assertEquals(self.isQueryable('gruenflaechen'), 0)
+        
+        # inherited setting in second layer
+        self.assertEquals(self.isQueryable('gewaesser'), 0)
+        
+        # explicit setting in second layer
+        self.assertEquals(self.isQueryable('sehenswuerdigkeiten'), 1)
+        
+        # explicit setting in third layer
+        self.assertEquals(self.isQueryable('strassen'), 1)
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/Extensions/wms/wms.py
===================================================================
--- packages/thuban/branches/upstream/current/Extensions/wms/wms.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Extensions/wms/wms.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,159 @@
+# Copyright (C) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
+# Bernhard Herzog <bh at intevation.de> (2004)
+# Martin Schulze <joey at infodrom.org> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Provide layers via OGC WMS.
+
+This extension is in a very experimental stage!
+It just demonstrates how to add a special
+layer into Thuban via an extension.
+Some things are not wired, so be prepared for Exceptions
+everywhere.
+"""
+
+__version__ = "$Revision: 2603 $"
+# $Source$
+# $Id: wms.py 2603 2005-04-26 15:04:22Z joey $
+
+import os, sys
+import xml.dom.minidom
+import tempfile
+
+from wxPython.wx import *
+
+from Thuban.Model.proj import Projection
+from Thuban.Model.extension import Extension
+from Thuban.UI.command import registry, Command
+from Thuban.UI.mainwindow import main_menu, layer_properties_dialogs
+from Thuban import _
+import Thuban.UI.baserenderer
+
+from layer import WMSLayer
+
+
+class WMSExtension(Extension):
+    def TreeInfo(self):
+        return (_("Extension: %s") % self.title,
+                [ object.TreeInfo() for object in self.objects ])
+
+
+def render_wms_layer(renderer, layer):
+    offx, offy = renderer.offset
+    width, height = renderer.dc.GetSizeTuple()
+
+    scale = renderer.scale
+    xmin = (0 - offx) / scale
+    ymin = (offy - height) / scale
+    xmax = (width - offx) / scale
+    ymax = (offy - 0) / scale
+
+    img, format = layer.GetMapImg(width, height, (xmin, ymin, xmax, ymax))
+
+    data = (width, height, (img, None, None))
+
+    renderer.draw_raster_data(layer, 0,0, data, format)
+
+    return ()
+
+Thuban.UI.baserenderer.add_renderer_extension(WMSLayer, render_wms_layer)
+from properties import wmsProperties
+layer_properties_dialogs.add(WMSLayer, wmsProperties)
+
+
+class SelectWMSServer(wxDialog):
+
+    ID_COMBOVALUE = 4003
+
+    def __init__(self, parent):
+        wxDialog.__init__(self, parent, -1, _("Select WMS Server"),
+            style = wxDEFAULT_DIALOG_STYLE
+                  | wxSYSTEM_MENU
+                  | wxRESIZE_BORDER)
+
+        self.combo_value = wxComboBox(self, self.ID_COMBOVALUE, size=(500,-1))
+        self.combo_value.Append("")
+        self.combo_value.Append('http://frida.intevation.org/cgi-bin/frida_wms?')
+        #self.combo_value.Append('http://wms.jpl.nasa.gov/wms.cgi?')
+        #self.combo_value.Append('http://eukrante.hq:9089/cgi-bin/wms_shg?')
+        #self.combo_value.Append('http://131.220.106.112:8080/deegree0.7/wms?')
+        #self.combo_value.Append('http://demo.cubewerx.com/demo/cubeserv/cubeserv.cgi?CONFIG=gita&')
+        self.combo_value.SetSelection(0)
+
+        button_ok = wxButton(self, wxID_OK, _("OK"))
+        button_ok.SetDefault()
+        button_close = wxButton(self, wxID_CANCEL, _("Close"))
+
+        vbox = wxBoxSizer(wxVERTICAL)
+        vbox.Add(self.combo_value, 1, wxEXPAND|wxALL|wxCB_SORT, 10)
+        hbox = wxBoxSizer(wxHORIZONTAL)
+        hbox.Add(button_ok, 0, wxALL, 10)
+        hbox.Add(button_close, 0, wxALL, 10)
+        vbox.Add(hbox, 0, 10)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(vbox)
+        vbox.Fit(self)
+        vbox.SetSizeHints(self)
+        self.Layout()
+
+        EVT_BUTTON(self, wxID_OK, self.OnOK)
+        EVT_BUTTON(self, wxID_CANCEL, self.OnCancel)
+
+    def OnOK(self, event):
+        self.url = self.combo_value.GetValue()
+        self.EndModal(wxID_OK)
+
+    def OnCancel(self, event):
+        self.EndModal(wxID_CANCEL)
+
+def wms_dialog(context):
+    """Request URL from user and add WMS Layer.
+
+    context -- The Thuban context.
+    """
+    dialog = SelectWMSServer(context.mainwindow)
+
+    if dialog.ShowModal() == wxID_OK:
+        url = dialog.url
+        if len(url) == 0:
+            url = None
+    else:
+        url = None
+    dialog.Destroy()
+
+    if url is None:
+        return
+
+    wms_layer = WMSLayer('A WMS Layer', url)
+    if wms_layer.error_msg is not None:
+        context.mainwindow.RunMessageBox(_('WMS'), wms_layer.error_msg)
+
+    map = context.mainwindow.canvas.Map()
+    if map.projection is None:
+        map.SetProjection(wms_layer.projection)
+    has_layers = map.HasLayers()
+    map.AddLayer(wms_layer)
+    if not has_layers:
+        # if we're adding a layer to an empty map, fit the
+        # new map to the window
+        context.mainwindow.canvas.FitMapToWindow()
+
+wxInitAllImageHandlers()
+wms_extension = WMSExtension('WMS')
+
+# register the new command
+registry.Add(Command('wms', _('Add WMS layer ...'), wms_dialog,
+                         helptext = _('Add a WMS Layer')))
+
+# find the experimental menu (create it anew if not found)
+experimental_menu = main_menu.FindOrInsertMenu('experimental',
+                                               _('Experimenta&l'))
+
+# finally add the new entry to the experimental menu
+experimental_menu.InsertItem('wms')

Added: packages/thuban/branches/upstream/current/MANIFEST.in
===================================================================
--- packages/thuban/branches/upstream/current/MANIFEST.in	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/MANIFEST.in	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,20 @@
+include README MANIFEST.in COPYING NEWS ChangeLog
+recursive-include libraries README COPYING LICENSE ChangeLog NEWS MANIFEST.in
+recursive-include libraries *.h *.c *.i *.py *.txt
+recursive-include test README *.py
+recursive-include po README Makefile thuban.pot *.po
+include thuban.py
+recursive-include Thuban *.py
+recursive-include Examples README *.py *.xpm
+recursive-include Extensions README *.py *.xpm *.diff *.apr *.txt
+recursive-include devtools *.py
+include Resources/Bitmaps/*.xpm
+recursive-include Resources/Locale/ *.mo
+include Resources/XML/*.dtd
+include Resources/Projections/*.proj
+recursive-include Doc Makefile README *.xmi *.xml *.png *.xcf *.sk *.ps *.txt
+include packaging/debian/changelog packaging/debian/control 
+include packaging/debian/copyright packaging/debian/docs 
+include packaging/debian/menu packaging/debian/rules 
+include packaging/debian/thuban.1 packaging/debian/watch
+include packaging/windows/thubanstart.py

Added: packages/thuban/branches/upstream/current/NEWS
===================================================================
--- packages/thuban/branches/upstream/current/NEWS	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/NEWS	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,281 @@
+Changes up to Thuban 1.2.0 (released 2007-03-13)
+==========================
+
+ - Python <= 2.4 calls C extension modules with the set locale.
+   This means those modules need to be robust against a locale
+   where LC_NUMERIC is set in a way that the decimal_point might
+   be a comma or something else. Problems are diagnosed 
+   at least with shapelib, proj and gdal. To cope with it we:
+
+   + Added a new option --setdecimalcommalocale to runtests.py so that
+   all tests can be checked with a comma as  decimal_point, if we
+   can find such an LC_NUMERIC. We only try a few in test/localessupport.py.
+
+   + Fixed behaviour with proj by switching to LC_NUMERIC "C" before
+   initialising the projection and afterward switch back.
+
+   + Added a workaround to internal shapelib and pyshapelib.
+   (Bernhard Reiter)
+
+ - Startup improved: We fail right away if the internal encoding could
+   not be determined. In this case, try to set the LANGUAGE variable to
+   one value and use no colon.
+   If we startup you can see the internal encoding in the about dialog now.
+   (Bernhard Reiter)
+
+ - Support for pysqlite2. (Didrik Pinte)
+
+ - Added packagin directory, which already has an example how
+   to load all extensions on windows. (Didrik Pinte)
+
+ - Updated code to support new style wxPython 2.6 imports. So
+   you need at least wyPython 2.6 . (Didrik Pinte)
+
+ - New Classification "Pattern": Classify text attributes by regexp. 
+   (Frank Koormann)
+
+ - New or Improved Extensions:
+
+    + Improved svxexport extension 1.0.1 (Bernhard Reiter)
+
+	* Fixed ARC layer writing: No filling is done.
+	You could actually get polylines with filling in between,
+	when the classification for the lines had a fill color.
+	E.g. this happens when you generate a classification from a ramp.
+
+	* Fixed label export.
+
+    + New export_shapefile extension (Jan-Oliver Wagner)
+      Available from the experimental menu.
+
+ - Known Problems with Extension OGR:
+	- Two tests fail (probably because of an ogr/shapelib problem.)
+	https://wald.intevation.org/tracker/index.php?func=detail&aid=91
+	- Is slower than native Shapefile support.
+	- Classification might not work.
+ 	
+
+Changes in Thuban 1.1.0
+=======================
+
+ - Thuban rembers directories in file selection dialogs during a thuban
+   session
+
+ - Add some support for wxPython 2.5 and 2.6.  Thuban is still
+   compatible with wxPython 2.4.
+
+ - Change the way thuban deals with non-ascii text.  The internal
+   representation is now the user's default encoding.  Thuban works a
+   bit better with a unicode build of wxPython but there are still
+   problems.  (Bernhard Herzog)
+
+ - Various raster data improvements.  Among other things, translucent
+   images are now supported on a sufficiently recent wxWidgets (2.6).
+   Also, only the part of the window actually covered by the image is
+   drawn.  (Jonathan Coles)
+
+ - Improved PostGIS support (Bernhard Herzog):
+
+    - support tables with multiple geometry columns.  The user can
+      select which one to use
+
+    - support tables with srids
+
+    - tables don't have to have a column named "gid" anymore.  The user
+      can select the column to use for ids
+
+    - PostgreSQL views are supported too
+
+    - support LINESTRING geometries
+
+    - support more PostgreSQL versions.  7.4 works now.
+
+ - Added support for sizable points (Jan-Oliver Wagner)
+
+ - When loading a (moved) session where shapefiles cannot be found, ask
+   the user (Frank Koormann)
+
+ - The middle mouse button can be used for panning now (Russell Nelson)
+
+ - Give a warning when the projection selected for a layer is probably
+   wrong (Russell Nelson)
+
+ - Updated shapelib
+
+ - New or improved extensions:
+
+    - A new extension which exports a map as SVG 
+      (Markus Rechtien, Bernhard Reiter)
+
+    - Improved WMS extension (Martin Schulze)
+
+    - New Extension to dump bounding boxes of all shapes of the selected
+      layer (Frank Koormann)
+
+    - New extension: umn_mapserver (Jan Schüngel)
+
+    - New extension: OGR (Nina Hüffmeyer)
+
+    - New Extension: mouseposition. Tool to collect mouse click positions
+      (map coordinates) in a dialog.  (Frank Koormann)
+
+ - Documentation:
+
+    - Add some documentation of the internals of Thuban.
+      See Doc/technotes/
+
+    - The thuban manual has been partly translated to German 
+      (Jan-Oliver Wagner)
+
+ - Updated translations: 
+       Russian (Alex Shevlakov)
+
+ - New translations:
+       Brazilian Portuguese (Eduardo Patto Kanegae)xb
+       Hungarian (Norbert Solymosi)
+
+
+Changes in Thuban 1.0.0
+=======================
+
+ - Updated translations:
+
+   Italian by Maurizio Napolitano
+   Spanish and French by Daniel Calvelo Aros
+   Russian by Alex Shevlakov
+
+ - some minor bug fixes
+
+
+Changes in Thuban 1.0rc1
+========================
+
+ - Redering improvements
+
+   Rendering the map in the main window does not freeze Thuban
+   completely anymore. While the rendering occurs the window is updated
+   regularly to show the progress and you can interact with the window
+   and thuban in general even when the rendering is not complete yet
+
+   The map display is also faster in many cases now, especially when
+   doing classifictions.
+
+   The renderes have a mechanism to define how new layer classes defined
+   in extensions can be rendered (see the new wms extension for an
+   example)
+
+ - Added a few extensions in the Extensions sub-directory. Most of them
+   are experimental to varying extents. Note that the binary packages
+   might not contain all of these extensions.
+
+   - gns2shp
+
+     Convert GNS (GEOnet Names Server) files to shapefiles. See
+     Extensions/gns2shp/gns2shp.py for more information
+
+   - wms
+
+     Use thuban as WMS client. See Extensions/wms/wms.py for more
+     information
+
+   - importAPR
+
+     Import a ArcView project file (.apr) and convert it to Thuban.
+
+   - profiling
+
+     For developers: perfomance measurement for the rendering code.
+     See Extensions/profiling/profiling.py for details.
+
+   - drawshape
+
+     This is a *very experimental* and potentially *dangerous* extension
+     to add shapes to a shapefile. Be careful with it as it may lead to
+     data loss. For more information, see Extensions/drawshape/README
+
+ - A new command line option --enable-attribute-editing, which when
+   given turns on editing of attribute values in the identify view. It
+   only works on layers whose attribute data is stored in DBF files.
+   This experimental and may lead to data loss, so be careful when using
+   it.
+
+ - EPSG projections
+
+   Thuban now comes with two .proj files containing EPSG projections
+   (epsg.proj and epsg-deprecated.proj in Resources/Projections/). These
+   projections can be shown in the dialog with the new check boxes under
+   "Show EPSG".
+
+ - Context menu in the legend window
+
+   The legend window now has a context menu for most of the layer
+   commands
+
+ - Localization updates
+
+   The localization is now done with wxWindow's localization support and
+   thus deals automatically with character encoding transformations and
+   the standard dialogs are also translated properly if the wxWindows
+   .mo files are installed
+
+   Updated translations for French and Spanish contributed by Daniel
+   Calvelo. Updated German translation
+
+ - PostGIS improvements
+
+   - Quote table and columns names properly.
+
+   - The dialog deals better with duplicate connections (e.g. trying to
+     create a new connection when there already is a connection for the
+     same database)
+
+ - Files written with the Windows version of Thuban can now be read by
+   the unix version. The other way round was already possible.
+
+ - The shapefile handling code now uses shapelib 1.2.10
+
+ - Thuban should work without problems and warnings with Python 2.3 now.
+
+
+Changes in Thuban 0.9
+=====================
+
+ - An initial version of the Thuban User's Manual. Currently only the
+   XML sources and the images are shipped with the Thuban sources. The
+   binary distributions do not contain the document at this point. An
+   online version is available at
+   http://thuban.intevation.org/documentation.html
+
+ - New Translations: German, Italian and Russian. The Italian and
+   Russion translations are based on 0.8.1 and therefore not quite up to
+   date. German is up to date, though. For 1.0 we intend to have a
+   translation period where all translations can be brought up to date.
+
+ - PostGIS support. This feaure is still a bit experimental at this
+   point and is not very well tested yet. It should work PostgreSQL
+   7.2.1 and postgis 0.7 as that's what we tested it with. Newer
+   versions probably also work.
+
+   The user as which the connection is established obviously needs
+   select permissions on any table to show and also on the
+   geometry_columns table.
+
+   Known Issues:
+
+    - Only four geometry types are currently supported: POINT,
+      MULTILINESTRING, POLYGON and MULTIPOLYGON.
+
+    - Tables must have a gid column which is assumed to be a non-NULL
+      integer which uniquely identifies the row.
+
+    - It's not optimized so some things may be very slow. For instance
+      the number of queries done could be reduced substantially
+      especially if you use classifications. Having an index on the gid
+      column can speed things up in that case. Note that at least older
+      versions shp2pgsql do not create such an index.
+
+ - Renamed the subdirectory extensions to libraries. The name extensions
+   can now be used for a directory with Thuban extensions.
+
+
+More changes in even more detail are listed in the ChangeLog file.

Added: packages/thuban/branches/upstream/current/PKG-INFO
===================================================================
--- packages/thuban/branches/upstream/current/PKG-INFO	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/PKG-INFO	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,11 @@
+Metadata-Version: 1.0
+Name: Thuban
+Version: 1.2.0
+Summary: Geographic data viewer
+Home-page: http://thuban.intevation.de/
+Author: Intevation GmbH
+Author-email: thuban at intevation.de
+License: GPL
+Description: Thuban is a viewer for geographic data written in Python
+        
+Platform: UNKNOWN

Added: packages/thuban/branches/upstream/current/README
===================================================================
--- packages/thuban/branches/upstream/current/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,115 @@
+
+Thuban - a Geographic Data Viewer
+=================================
+
+$Date: 2007-03-13 22:21:51 +0000 (Di, 13 Mär 2007) $
+$Revision: 2736 $
+
+Thuban is an interactive viewer for geographic data.  
+Python and the wxWidgets framework ensure great portability.
+Thuban is Free Software and runs on GNU/Linux, Windows 
+and several other operating systems.
+
+Homepage: 			https://thuban.intevation.org
+Development infrastructure:  	https://wald.intevation.org/projects/thuban/
+
+About the Name
+--------------
+
+Thuban is the name of a star in the constellation Draco (The Dragon).
+About 4000 years ago it was the north star.
+
+
+Requirements
+------------
+
+Thuban requires the following software to be installed:
+
+  Python     2.2.1    http://www.python.org
+  wxWidgets  2.6.3.2  http://www.wxwidgets.org (formerly known as wxWindows)
+  wxPython   2.6.3.2  http://www.wxpython.org
+  proj       4.4.5    http://www.remotesensing.org/proj/
+  SQLite     2.8.3    http://sqlite.org/
+  PySQLite   1.0.1    http://pysqlite.org/
+
+The versions given are the lowest versions that are known to work. for
+proj, sqlite and pysqlite somewhat older versions probably work as well.
+Note that the wxPython version must be the same as the wxWidgets version
+(Some wxPython binary packages already contain the right wxWidgets version)
+
+Optional software:
+
+  GDAL       1.3.2  http://www.remotesensing.org/gdal/
+     for raster image (geo-tiff) support
+
+  psycopg    1.0.x  http://initd.org/software/psycopg
+     for postgis connections. Newer version probably also work
+
+  RXP        1.2.x  http://www.cogsci.ed.ac.uk/~richard/rxp.html
+     usually comes directly with pyRXP.
+  pyRXP      0.9    http://www.reportlab.org/pyrxp.html
+     only for the automatic tests to validate Thuban's XML files.
+
+
+Installation
+------------
+
+Building Thuban (this compiles the extension modules but leaves them in
+a directory under build/):
+
+   python setup.py build
+
+
+To setup Thuban to run directly from the source directory:
+
+   python setup.py install_local
+
+You can run this without running build first.
+
+
+To install Thuban:
+
+   python setup.py install
+
+
+for general information about the command line options of the setup.py
+script, run
+
+   python setup.py --help
+
+
+If you build from SVN and want to have translated menus, dialogs etc.
+you have to build the message catalogs manually before you run setup.py.
+See po/README for more information.
+
+
+Build Troubleshooting
+---------------------
+
+When building Thuban, you might have problems because of a missing file
+wx/wxPython/wxPython.h.  This file is part of wxPython and may be
+packaged in a separate package.  Unfortunately, on some systems this
+file is not packaged at all.  On those systems you can try a work-around
+built into Thuban, by passing the --use-wx-python-swig-hack to the
+build_ext command.  This can be done on the command line for the build
+command like this:
+
+   python setup.py  build_ext --use-wx-python-swig-hack  build
+
+You can also use it with the install_local command:
+
+   python setup.py  build_ext --use-wx-python-swig-hack  install_local
+
+Note, that this work-around relies on some wxPython internals and may
+cease to work at some point.  We tested it with wxPython 2.6.
+
+
+License
+-------
+
+Thuban is licensed under the terms of the 
+GNU General Public License (GPL) version 2 or later.
+
+However, some of the extension modules in the extension subdirectory are
+licensed under other Free Software licenses. 
+See the respective README files for details.

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/bottom_layer.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/bottom_layer.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/bottom_layer.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,31 @@
+/* XPM */
+static char * bottom_layer_xpm[] = {
+"24 24 4 1",
+" 	c None",
+".	c #000000",
+"+	c #FFFFFF",
+"@	c #949194",
+"                        ",
+"                        ",
+"                        ",
+"             ...........",
+"            .+++++++++. ",
+"           .+++++++++.  ",
+"       ....+++++++++.   ",
+"      .++.+++++++++.    ",
+"     .++...........     ",
+"    .+++++++++..........",
+"   .+++++++++.++++++++. ",
+"  ...........++++++++.  ",
+"          .+++++++++....",
+"         .+++++++++.++. ",
+"        ...........++.  ",
+"          .+++++++++....",
+"     .   .+++++++++.++.@",
+"     .. ...........++.@@",
+" .......  .+++++++++.@@ ",
+"     ..  .+++++++++.@@  ",
+"     .  ...........@@   ",
+"         @@@@@@@@@@@    ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/close_12.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/close_12.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/close_12.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,17 @@
+/* XPM */
+static char * close_12_xpm[] = {
+"12 12 2 1",
+" 	c None",
+".	c #000000",
+"            ",
+"            ",
+"  .      .  ",
+"   .    .   ",
+"    .  .    ",
+"     ..     ",
+"     ..     ",
+"    .  .    ",
+"   .    .   ",
+"  .      .  ",
+"            ",
+"            "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/dock_12.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/dock_12.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/dock_12.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,20 @@
+/* XPM */
+static char * dock_12_xpm[] = {
+"12 12 5 1",
+" 	c None",
+".	c #000000",
+"+	c #949194",
+"@	c #5A5D5A",
+"#	c #FFFFFF",
+"            ",
+"            ",
+"            ",
+"  ......... ",
+"  .....+++@ ",
+"  @###@+++@ ",
+"  @###@+++@ ",
+"  @###@+++@ ",
+"  @###@+++@ ",
+"  @###@+++@ ",
+"  @@@@@@@@@ ",
+"            "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/fullextent.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/fullextent.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/fullextent.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,30 @@
+/* XPM */
+static char * fullextent_xpm[] = {
+"24 24 3 1",
+" 	c None",
+".	c #000000",
+"+	c #949194",
+"                        ",
+" ......          ...... ",
+" .++++++          ++++.+",
+" .+                   .+",
+" .+                   .+",
+" .+  ....      ....   .+",
+" .+  ...++      ...+  .+",
+"  +  ...+       ...+   +",
+"     .++.      . +.+    ",
+"      +  .    . +  +    ",
+"          +    +        ",
+"                        ",
+"                        ",
+"                        ",
+"         .    .         ",
+"     .  . +    .  .     ",
+"     ... +      ...+    ",
+" .   ...+       ...+  . ",
+" .+  ....      ....+  .+",
+" .+   ++++      ++++  .+",
+" .+                   .+",
+" .+                   .+",
+" ......          ......+",
+"  ++++++          ++++++"};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/fulllayerextent.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/fulllayerextent.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/fulllayerextent.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,32 @@
+/* XPM */
+static char * fulllayerextent_xpm[] = {
+"24 24 5 1",
+" 	c None",
+".	c #727272",
+"+	c #FFFFFF",
+"@	c #000000",
+"#	c #949194",
+"                        ",
+"                        ",
+"      ...         .     ",
+"     .+++.      ..+..   ",
+"    .+++++.   ..+++++.  ",
+"   .+@@@@++...+@@@@++.  ",
+"   .+@@@##++++++@@@#+.  ",
+"   .+@@@#+++++++@@@#+.  ",
+"   .+@##@++++++ at +#@#+.  ",
+"   .++#++ at ++++@+#++#+.  ",
+"    .+++++#++++#++++.   ",
+"     .++++++++++++++.   ",
+"      .++++++++++++.    ",
+"       ..++++++++++.    ",
+"         @++++ at +++++.   ",
+"     @  @ #++++ at ++@+.   ",
+"     @@@ # .++++@@@#.   ",
+"     @@@#   .+++@@@#.   ",
+"     @@@@    .+@@@@#.   ",
+"      ####    .+####.   ",
+"              .++...    ",
+"               ..       ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/fullselextent.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/fullselextent.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/fullselextent.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,33 @@
+/* XPM */
+static char * fullselextent_xpm[] = {
+"24 24 6 1",
+" 	c None",
+".	c #A8A8A8",
+"+	c #000000",
+"@	c #949194",
+"#	c #727272",
+"$	c #FFFFFF",
+"                        ",
+"                        ",
+"      ...         .     ",
+"   + .   .      .. +.   ",
+"    +  +  .   .+  + @.  ",
+"   . +++@  ... +++ @ .  ",
+"   . +++@  .   +++@  .  ",
+"   .++++@ ##   ++++  .  ",
+"   . @@@@#$#    @@@@ .  ",
+"   .   ##$$$###      .  ",
+"    . #$$$$$$$$#    .   ",
+"     #$$$$$$$$$$#   .   ",
+"      #$$$$$$$$$$#...   ",
+"       ##$$$$$$$#   .   ",
+"         #$$$$##    .   ",
+"          #$##      .   ",
+"    ++++   #   ++++ .   ",
+"     +++@  ..  +++@@.   ",
+"     +++@   .. +++@ .   ",
+"    + @+@    ..+@@+ .   ",
+"   + @  @     . @..+    ",
+"    @          ..   @   ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,29 @@
+/* XPM */
+static char * group_use_xpm[] = {
+"24 24 2 1",
+" 	c None",
+".	c #000000",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"         ..             ",
+"         ...            ",
+"          ...           ",
+"           ...          ",
+"            ...         ",
+"             ...        ",
+"              ...       ",
+"              ...       ",
+"             ...        ",
+"            ...         ",
+"           ...          ",
+"          ...           ",
+"         ...            ",
+"         ..             ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_all.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_all.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_all.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,29 @@
+/* XPM */
+static char * group_use_all_xpm[] = {
+"24 24 2 1",
+" 	c None",
+".	c #000000",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"     ..     ..          ",
+"     ...    ...         ",
+"      ...    ...        ",
+"       ...    ...       ",
+"        ...    ...      ",
+"         ...    ...     ",
+"          ...    ...    ",
+"          ...    ...    ",
+"         ...    ...     ",
+"        ...    ...      ",
+"       ...    ...       ",
+"      ...    ...        ",
+"     ...    ...         ",
+"     ..     ..          ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_none.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_none.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_none.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,29 @@
+/* XPM */
+static char * group_use_none_xpm[] = {
+"24 24 2 1",
+" 	c None",
+".	c #000000",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"          ..     ..     ",
+"         ...    ...     ",
+"        ...    ...      ",
+"       ...    ...       ",
+"      ...    ...        ",
+"     ...    ...         ",
+"    ...    ...          ",
+"    ...    ...          ",
+"     ...    ...         ",
+"      ...    ...        ",
+"       ...    ...       ",
+"        ...    ...      ",
+"         ...    ...     ",
+"          ..     ..     ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_not.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_not.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/group_use_not.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,29 @@
+/* XPM */
+static char * group_use_not_xpm[] = {
+"24 24 2 1",
+" 	c None",
+".	c #000000",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"             ..         ",
+"            ...         ",
+"           ...          ",
+"          ...           ",
+"         ...            ",
+"        ...             ",
+"       ...              ",
+"       ...              ",
+"        ...             ",
+"         ...            ",
+"          ...           ",
+"           ...          ",
+"            ...         ",
+"             ..         ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/hide_layer.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/hide_layer.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/hide_layer.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,29 @@
+/* XPM */
+static char * hide_layer_xpm[] = {
+"24 23 3 1",
+" 	c None",
+".	c #000000",
+"+	c #949194",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"        .......         ",
+"      ...     ...       ",
+"    ...         ...     ",
+"   ..             ..    ",
+"  ..               ..   ",
+" ..                 ..  ",
+" ..                  .+ ",
+" ....               ..+ ",
+"  ....           ....++ ",
+"   ......     ......++  ",
+"    ...............++   ",
+"     +...........+++    ",
+"       +.......+++      ",
+"         +++++++        ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/identify.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/identify.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/identify.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,30 @@
+/* XPM */
+static char * identify_xpm[] = {
+"24 24 3 1",
+" 	c None",
+".	c #000000",
+"+	c #949194",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"    .                   ",
+"    .+        ....      ",
+"    ..       ......     ",
+"    ..+     ..++++..    ",
+"    ...     .++   ..+   ",
+"    ...+    .+    ..+   ",
+"    ....     +    ..+   ",
+"    ....+        ..++   ",
+"    .....       ..++    ",
+"    .....+     ..++     ",
+"    ......     ..+      ",
+"    ......+    ..+      ",
+"    .......     ++      ",
+"    ...+...+            ",
+"    ..++ ...   ..       ",
+"    .++   +.+  ..+      ",
+"     +      +   ++      ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/label.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/label.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/label.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,30 @@
+/* XPM */
+static char * label_xpm[] = {
+"24 24 3 1",
+" 	c None",
+".	c #000000",
+"+	c #949194",
+"                        ",
+"                        ",
+"                        ",
+"   .         ...        ",
+"   .+         .++       ",
+"   ..         .+        ",
+"   ..+        .+        ",
+"   ...        .+        ",
+"   ...+       .+        ",
+"   ....       .+        ",
+"   ....+      .+        ",
+"   .....      .+        ",
+"   .....+     .+        ",
+"   ......     .+        ",
+"   ......+    .+        ",
+"   .......    .+        ",
+"   ...+...+   .+        ",
+"   ..++ ...   .+        ",
+"   .++   +.+ ...        ",
+"    +     ++  +++       ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/layer_properties.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/layer_properties.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/layer_properties.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,32 @@
+/* XPM */
+static char * layer_properties_xpm[] = {
+"24 24 5 1",
+" 	c None",
+".	c #000000",
+"+	c #313031",
+"@	c #949194",
+"#	c #FFFFFF",
+"                        ",
+"           ........  +++",
+"          .@@@@@@@...+++",
+"         .@@@@@@@@@@@+++",
+"        .@@@@@@@@@@@@+++",
+"       .@@.@@@@@@@@@@+++",
+" ......@@.@@.@@@@@@@@+++",
+" .##+.@@.@@.@@.@@@@@@+++",
+" .##.@@.. at .@@.@@@@@..+++",
+" .#.@@.##.@@.@@..... at +++",
+" .#. at .####..@@.####.@   ",
+" .##.#######..#####.@   ",
+" .##++++##+++++++##.@   ",
+" .##+##############.@   ",
+" .##+##############.@   ",
+" .##++++##+++++++##.@   ",
+" .##+##############.@   ",
+" .##+##############.@   ",
+" .##++++##+++++++##.@   ",
+" .#################.@   ",
+" ...................@   ",
+"  @@@@@@@@@@@@@@@@@@@   ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/legend_icon_layer.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/legend_icon_layer.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/legend_icon_layer.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,22 @@
+/* XPM */
+static char * legend_icon_map_xpm[] = {
+"16 16 3 1",
+" 	c None",
+".	c #FFFFFF",
+"+	c #000000",
+"................",
+"................",
+"................",
+"................",
+"................",
+".....+++++++++++",
+"....+.........+.",
+"...+.........+..",
+"..+.........+...",
+".+.........+....",
+"+++++++++++.....",
+"................",
+"................",
+"................",
+"................",
+"................"};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/legend_icon_map.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/legend_icon_map.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/legend_icon_map.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,61 @@
+/* XPM */
+static char * map_xpm[] = {
+"15 15 43 1",
+" 	c None",
+".	c #739FBE",
+"+	c #E8ECF1",
+"@	c #5A9152",
+"#	c #6696B8",
+"$	c #5189B0",
+"%	c #3B7BA6",
+"&	c #3476A3",
+"*	c #588EB3",
+"=	c #7AA4C1",
+"-	c #97B7CE",
+";	c #A7C1D5",
+">	c #427FA9",
+",	c #5F92B5",
+"'	c #DBE3EB",
+")	c #6C9BBB",
+"!	c #856D5F",
+"~	c #47391A",
+"{	c #4984AC",
+"]	c #5DAC62",
+"^	c #1C8129",
+"/	c #42904B",
+"(	c #B4CADA",
+"_	c #81A8C4",
+":	c #4B9953",
+"<	c #F5F4F6",
+"[	c #8AAEC8",
+"}	c #CEDBE5",
+"|	c #5FAC63",
+"1	c #277333",
+"2	c #166F23",
+"3	c #327E3C",
+"4	c #145E21",
+"5	c #2B7736",
+"6	c #105A1E",
+"7	c #C1D2E0",
+"8	c #176124",
+"9	c #1A6527",
+"0	c #35813F",
+"a	c #216C2D",
+"b	c #2E7A39",
+"c	c #54A35A",
+"d	c #398643",
+".+@#$%%&&&%%.#%",
+"*=-;*>%%%%%,'#>",
+"$)!~){>>>>>*]){",
+",+^/)*{>>>{#@(,",
+"*!'^-#${{{$*_:<",
+"$#[<^--$$$$*.}^",
+"{.^|][#,***,#12",
+"{-^3:;~.,,,#)_1",
+"$)[<4:+'-)##)=]",
+"*5/6/]^@;7+;=_;",
+"@^8^^^^5^^9^5@'",
+"_08^a4^:^1|^^'(",
+"*[61/]^!-(;.._-",
+"$#[~2b}+[###)=/",
+"{-!cd-;.,*,,)_d"};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/lower_layer.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/lower_layer.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/lower_layer.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,31 @@
+/* XPM */
+static char * lower_layer_xpm[] = {
+"24 24 4 1",
+" 	c None",
+".	c #000000",
+"+	c #FFFFFF",
+"@	c #949194",
+"                        ",
+"                        ",
+"                        ",
+"            ........... ",
+"           .+++++++++.  ",
+"          .+++++++++.   ",
+"      ....+++++++++.    ",
+"     .++.+++++++++.     ",
+"    .++...........      ",
+"   .+++++++++.........  ",
+"  .+++++++++.+++++++.   ",
+" ...........+++++++.    ",
+"        .+++++++++....  ",
+"   .   .+++++++++.++.   ",
+"   .  ...........++.    ",
+"   .    .+++++++++....@ ",
+"   .   .+++++++++.++.@  ",
+"   .  ...........++.@@  ",
+"   .    .+++++++++.@@   ",
+" ..... .+++++++++.@@    ",
+"  ... ...........@@     ",
+"   .   @@@@@@@@@@@      ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/pan.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/pan.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/pan.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,30 @@
+/* XPM */
+static char * pan_xpm[] = {
+"24 24 3 1",
+" 	c None",
+".	c #000000",
+"+	c #949194",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"           .            ",
+"          ...           ",
+"         .....          ",
+"           .+++         ",
+"           .+           ",
+"      .    .+   .       ",
+"     ..    .+   ..      ",
+"    ...............     ",
+"     ..++++.++++..++    ",
+"      .+   .+   .++     ",
+"       +   .+    +      ",
+"           .+           ",
+"         .....          ",
+"          ...+          ",
+"           .+           ",
+"           +            ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/raise_layer.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/raise_layer.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/raise_layer.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,31 @@
+/* XPM */
+static char * raise_layer_xpm[] = {
+"24 24 4 1",
+" 	c None",
+".	c #000000",
+"+	c #FFFFFF",
+"@	c #949194",
+"                        ",
+"                        ",
+"                        ",
+"            ........... ",
+"   .       .+++++++++.  ",
+"  ...     .+++++++++.   ",
+" .....   .+++++++++.... ",
+"   .    .+++++++++.++.  ",
+"   .   ...........++.   ",
+"   .     .+++++++++...  ",
+"   .    .+++++++++.+.   ",
+"   .   ...........+.    ",
+"   .  ...+++++++++.     ",
+"     .+.+++++++++.      ",
+"    .+...........       ",
+"   .+++++++++.........@ ",
+"  .+++++++++.+++++++.@  ",
+" ...........+++++++.@@  ",
+"        .+++++++++.@@   ",
+"       .+++++++++.@@    ",
+"      ...........@@     ",
+"       @@@@@@@@@@@      ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/show_layer.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/show_layer.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/show_layer.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,30 @@
+/* XPM */
+static char * show_layer_xpm[] = {
+"24 23 4 1",
+" 	c None",
+".	c #000000",
+"+	c #FFFFFF",
+"@	c #949194",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"        .......         ",
+"      ...........       ",
+"    ...............     ",
+"   .................    ",
+"  ....++....+..++....   ",
+" ....++.........+++...  ",
+" ..++++.........+++++.@ ",
+" ..++++.........++++..@ ",
+"  ...+++.......++++..@@ ",
+"   ...++.......++...@@  ",
+"    ....+.....+....@@   ",
+"     @...........@@@    ",
+"       @.......@@@      ",
+"         @@@@@@@        ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/top_layer.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/top_layer.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/top_layer.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,31 @@
+/* XPM */
+static char * top_layer_xpm[] = {
+"24 24 4 1",
+" 	c None",
+".	c #000000",
+"+	c #FFFFFF",
+"@	c #949194",
+"                        ",
+"                        ",
+"                        ",
+"     .      ........... ",
+"     ..    .+++++++++.  ",
+" .......  .+++++++++.   ",
+"     ..  .+++++++++.... ",
+"     .  .+++++++++.++.  ",
+"       ...........++.   ",
+"         .+++++++++...  ",
+"        .+++++++++.+.   ",
+"       ...........+.    ",
+"      ...+++++++++.     ",
+"     .+.+++++++++.      ",
+"    .+...........       ",
+"   .+++++++++.........@ ",
+"  .+++++++++.+++++++.@  ",
+" ...........+++++++.@@  ",
+"        .+++++++++.@@   ",
+"       .+++++++++.@@    ",
+"      ...........@@     ",
+"       @@@@@@@@@@@      ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/undock_12.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/undock_12.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/undock_12.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,20 @@
+/* XPM */
+static char * undock_12_xpm[] = {
+"12 12 5 1",
+" 	c None",
+".	c #000000",
+"+	c #5A5D5A",
+"@	c #FFFFFF",
+"#	c #949194",
+"            ",
+" .....      ",
+" +@@@+      ",
+" +@@@+..... ",
+" +@@@+####+ ",
+" +@@@+####+ ",
+" +@@@+####+ ",
+" +++++####+ ",
+"  +#######+ ",
+"  +#######+ ",
+"  +++++++++ ",
+"            "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/zoom_in.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/zoom_in.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/zoom_in.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,34 @@
+/* XPM */
+static char * zoom_in_xpm[] = {
+"24 24 7 1",
+" 	c None",
+".	c #000000",
+"+	c #949194",
+"@	c #DEDADE",
+"#	c #FFFFFF",
+"$	c #D5D6D5",
+"%	c #D6D1D6",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"            ....        ",
+"          +.@##$.+      ",
+"          .##++##.+     ",
+"         .@#+####@.     ",
+"         .#+######.+    ",
+"         .########.+    ",
+"         .@######@.+    ",
+"          .######.++    ",
+"         ...@##@.++     ",
+"        ...+....++      ",
+"       ...++ ++++       ",
+"      ...++    ..       ",
+"     ...++     ..%      ",
+"    ...++    ......     ",
+"    +.++     ......%    ",
+"     ++       %..%%%    ",
+"               ..%      ",
+"                %%      ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Bitmaps/zoom_out.xpm
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Bitmaps/zoom_out.xpm	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Bitmaps/zoom_out.xpm	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,34 @@
+/* XPM */
+static char * zoom_out_xpm[] = {
+"24 24 7 1",
+" 	c None",
+".	c #000000",
+"+	c #D6D1D6",
+"@	c #949194",
+"#	c #DEDADE",
+"$	c #FFFFFF",
+"%	c #D5D6D5",
+"                        ",
+"                        ",
+"                        ",
+"                        ",
+"            ....        ",
+"          @.#$$%.@      ",
+"          .$$@@$$.@     ",
+"         .#$@$$$$#.     ",
+"         .$@$$$$$$.@    ",
+"         .$$$$$$$$.@    ",
+"         .#$$$$$$#.@    ",
+"          .$$$$$$.@@    ",
+"         ...#$$#.@@     ",
+"        ... at ....@@      ",
+"       ...@@ @@@@       ",
+"      ...@@             ",
+"     ...@@              ",
+"    ...@@    ......     ",
+"    @.@@     ......+    ",
+"     @@       ++++++    ",
+"                        ",
+"                        ",
+"                        ",
+"                        "};

Added: packages/thuban/branches/upstream/current/Resources/Locale/de/LC_MESSAGES/thuban.mo
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Resources/Locale/de/LC_MESSAGES/thuban.mo
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Resources/Locale/es/LC_MESSAGES/thuban.mo
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Resources/Locale/es/LC_MESSAGES/thuban.mo
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Resources/Locale/fr/LC_MESSAGES/thuban.mo
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Resources/Locale/fr/LC_MESSAGES/thuban.mo
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Resources/Locale/hu/LC_MESSAGES/thuban.mo
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Resources/Locale/hu/LC_MESSAGES/thuban.mo
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Resources/Locale/it/LC_MESSAGES/thuban.mo
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Resources/Locale/it/LC_MESSAGES/thuban.mo
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Resources/Locale/pt_BR/LC_MESSAGES/thuban.mo
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Resources/Locale/pt_BR/LC_MESSAGES/thuban.mo
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Resources/Locale/ru/LC_MESSAGES/thuban.mo
===================================================================
(Binary files differ)


Property changes on: packages/thuban/branches/upstream/current/Resources/Locale/ru/LC_MESSAGES/thuban.mo
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: packages/thuban/branches/upstream/current/Resources/Projections/defaults.proj
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Projections/defaults.proj	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Projections/defaults.proj	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE projectionlist SYSTEM "projfile.dtd">
+<projectionlist>
+    <projection name="UTM Zone 27">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=27"/>
+        <parameter value="ellps=clrk66"/>
+    </projection>
+    <projection name="Gauss-Krueger Zone 2 (Germany)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0.0"/>
+        <parameter value="lon_0=6.0"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="k=1.0"/>
+        <parameter value="ellps=bessel"/>
+    </projection>
+    <projection name="UK National Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=49"/>
+        <parameter value="lon_0=-2"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=-100000"/>
+        <parameter value="k=0.999601"/>
+        <parameter value="ellps=airy"/>
+    </projection>
+    <projection name="Geographic">
+        <parameter value="proj=latlong"/>
+        <parameter value="to_meter=0.017453292519943295"/>
+        <parameter value="ellps=clrk66"/>
+    </projection>
+    <projection name="Belgian Datum 1972">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49.83333339"/>
+        <parameter value="lat_2=51.16666723"/>
+        <parameter value="lat_0=90.0"/>
+        <parameter value="lon_0=4.367486667"/>
+        <parameter value="x_0=150000.013"/>
+        <parameter value="y_0=5400088.438"/>
+        <parameter value="ellps=intl"/>
+    </projection>
+    <projection name="Gauss-Boaga Zone 1 (Italy)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=9"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="k=0.9996"/>
+        <parameter value="ellps=intl"/>
+    </projection>
+    <projection name="Reseau geodesique francais (Lambert-93)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.0"/>
+        <parameter value="lat_2=49.0"/>
+        <parameter value="lat_0=46.5"/>
+        <parameter value="lon_0=3.0"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=66000000"/>
+        <parameter value="ellps=GRS80"/>
+    </projection>
+</projectionlist>

Added: packages/thuban/branches/upstream/current/Resources/Projections/epsg-deprecated.proj
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Projections/epsg-deprecated.proj	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Projections/epsg-deprecated.proj	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE projfile SYSTEM "projectionlist.dtd">
+<projectionlist>
+    <projection epsg="31493" name="DHDN / Germany zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0.000000000"/>
+        <parameter value="lon_0=9.000000000"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=3500000.000"/>
+        <parameter value="y_0=0.000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+    </projection>
+</projectionlist>

Added: packages/thuban/branches/upstream/current/Resources/Projections/epsg.proj
===================================================================
--- packages/thuban/branches/upstream/current/Resources/Projections/epsg.proj	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/Projections/epsg.proj	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,24981 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE projfile SYSTEM "projectionlist.dtd">
+<projectionlist>
+    <projection epsg="2000" name="Anguilla 1957 / British West Indies Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-62"/>
+        <parameter value="k=0.999500"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2001" name="Antigua 1943 / British West Indies Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-62"/>
+        <parameter value="k=0.999500"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-255,-15,71,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2002" name="Dominica 1945 / British West Indies Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-62"/>
+        <parameter value="k=0.999500"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=725,685,536,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2003" name="Grenada 1953 / British West Indies Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-62"/>
+        <parameter value="k=0.999500"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=72,213.7,93,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2004" name="Montserrat 58 / British West Indies Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-62"/>
+        <parameter value="k=0.999500"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=174,359,365,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2005" name="St Kitts 1955 / British West Indies Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-62"/>
+        <parameter value="k=0.999500"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=9,183,236,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2006" name="St Lucia 1955 / British West Indies Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-62"/>
+        <parameter value="k=0.999500"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-149,128,296,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2007" name="St Vincent 45 / British West Indies Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-62"/>
+        <parameter value="k=0.999500"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2008" name="NAD27(CGQ77) / SCoPQ zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-55.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2009" name="NAD27(CGQ77) / SCoPQ zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-58.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2010" name="NAD27(CGQ77) / SCoPQ zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-61.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2011" name="NAD27(CGQ77) / SCoPQ zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-64.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2012" name="NAD27(CGQ77) / SCoPQ zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-67.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2013" name="NAD27(CGQ77) / SCoPQ zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-70.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2014" name="NAD27(CGQ77) / SCoPQ zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-73.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2015" name="NAD27(CGQ77) / SCoPQ zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-76.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2016" name="NAD27(CGQ77) / SCoPQ zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-79.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2017" name="NAD27(76) / MTM zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-73.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2018" name="NAD27(76) / MTM zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-76.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2019" name="NAD27(76) / MTM zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-79.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2020" name="NAD27(76) / MTM zone 11">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-82.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2021" name="NAD27(76) / MTM zone 12">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2022" name="NAD27(76) / MTM zone 13">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-84"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2023" name="NAD27(76) / MTM zone 14">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-87"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2024" name="NAD27(76) / MTM zone 15">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2025" name="NAD27(76) / MTM zone 16">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-93"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2026" name="NAD27(76) / MTM zone 17">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-96"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2027" name="NAD27(76) / UTM zone 15N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=15"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2028" name="NAD27(76) / UTM zone 16N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=16"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2029" name="NAD27(76) / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2030" name="NAD27(76) / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2031" name="NAD27(CGQ77) / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2032" name="NAD27(CGQ77) / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2033" name="NAD27(CGQ77) / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2034" name="NAD27(CGQ77) / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2035" name="NAD27(CGQ77) / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2036" name="NAD83(CSRS98) / New Brunswick Stereo">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=46.5"/>
+        <parameter value="lon_0=-66.5"/>
+        <parameter value="k=0.999912"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=7500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2037" name="NAD83(CSRS98) / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2038" name="NAD83(CSRS98) / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2039" name="Israel / Israeli TM Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31.73439361111111"/>
+        <parameter value="lon_0=35.20451694444445"/>
+        <parameter value="k=1.000007"/>
+        <parameter value="x_0=219529.584"/>
+        <parameter value="y_0=626907.39"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2040" name="Locodjo 1965 / UTM zone 30N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-125,53,467,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2041" name="Abidjan 1987 / UTM zone 30N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-124.76,53,466.79,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2042" name="Locodjo 1965 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-125,53,467,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2043" name="Abidjan 1987 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-124.76,53,466.79,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2044" name="Hanoi 1972 / Gauss-Kruger zone 18">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=18500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-17.51,-108.32,-62.39,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2045" name="Hanoi 1972 / Gauss-Kruger zone 19">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=19500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-17.51,-108.32,-62.39,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2057" name="Rassadiran / Nakhl e Taqi">
+        <parameter value="proj=omerc"/>
+        <parameter value="lat_0=27.51882880555555"/>
+        <parameter value="lonc=52.60353916666667"/>
+        <parameter value="alpha=0.5716611944444444"/>
+        <parameter value="k=0.999895934"/>
+        <parameter value="x_0=658377.437"/>
+        <parameter value="y_0=3044969.194"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-133.63,-157.5,-158.62,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2058" name="ED50(ED77) / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2059" name="ED50(ED77) / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2060" name="ED50(ED77) / UTM zone 40N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2061" name="ED50(ED77) / UTM zone 41N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=41"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2062" name="Madrid 1870 (Madrid) / Spain">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-3.687938888888889"/>
+        <parameter value="k_0=0.9988085293"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=600000"/>
+        <parameter value="a=6378298.3"/>
+        <parameter value="b=6356657.142669562"/>
+        <parameter value="pm=madrid"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2063" name="Dabola 1981 / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-23,259,-9,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2064" name="Dabola 1981 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-23,259,-9,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2065" name="S-JTSK (Ferro) / Krovak">
+        <parameter value="proj=krovak"/>
+        <parameter value="lat_0=49.5"/>
+        <parameter value="lon_0=24.83333333333333"/>
+        <parameter value="alpha=30.28813972222222"/>
+        <parameter value="k=0.9999"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=ferro"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2066" name="Mount Dillon / Tobago Grid">
+        <parameter value="proj=cass"/>
+        <parameter value="lat_0=11.25217861111111"/>
+        <parameter value="lon_0=-60.68600888888889"/>
+        <parameter value="x_0=37718.66154375"/>
+        <parameter value="y_0=36209.915082"/>
+        <parameter value="a=6378293.63683822"/>
+        <parameter value="b=6356617.979337744"/>
+        <parameter value="to_meter=0.2011661949"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2067" name="Naparima 1955 / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2068" name="ELD79 / Libya zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=9"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2069" name="ELD79 / Libya zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=11"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2070" name="ELD79 / Libya zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=13"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2071" name="ELD79 / Libya zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2072" name="ELD79 / Libya zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=17"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2073" name="ELD79 / Libya zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=19"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2074" name="ELD79 / Libya zone 11">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2075" name="ELD79 / Libya zone 12">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=23"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2076" name="ELD79 / Libya zone 13">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2077" name="ELD79 / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2078" name="ELD79 / UTM zone 33N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2079" name="ELD79 / UTM zone 34N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2080" name="ELD79 / UTM zone 35N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2081" name="Chos Malal 1914 / Argentina zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lon_0=-69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2082" name="Pampa del Castillo / Argentina zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lon_0=-69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2083" name="Hito XVIII 1963 / Argentina zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lon_0=-69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=18.38,192.45,96.82,0.056,-0.142,-0.2,-0.0013"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2084" name="Hito XVIII 1963 / UTM zone 19S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=18.38,192.45,96.82,0.056,-0.142,-0.2,-0.0013"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2085" name="NAD27 / Cuba Norte">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=22.35"/>
+        <parameter value="lat_0=22.35"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="k_0=0.99993602"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=280296.016"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2086" name="NAD27 / Cuba Sur">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=20.71666666666667"/>
+        <parameter value="lat_0=20.71666666666667"/>
+        <parameter value="lon_0=-76.83333333333333"/>
+        <parameter value="k_0=0.99994848"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=229126.939"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2087" name="ELD79 / TM 12 NE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=12"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2088" name="Carthage / TM 11 NE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=11"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2089" name="Yemen NGN96 / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2090" name="Yemen NGN96 / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2091" name="South Yemen / Gauss Kruger zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=8500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-76,-138,67,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2092" name="South Yemen / Gauss Kruger zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=9500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-76,-138,67,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2093" name="Hanoi 1972 / GK 106 NE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=106"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-17.51,-108.32,-62.39,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2094" name="WGS 72BE / TM 106 NE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=106"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2095" name="Bissau / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-173,253,27,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2096" name="Korean 1985 / Korea East Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2097" name="Korean 1985 / Korea Central Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=127"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2098" name="Korean 1985 / Korea West Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=125"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2099" name="Qatar 1948 / Qatar Grid">
+        <parameter value="proj=cass"/>
+        <parameter value="lat_0=25.38236111111111"/>
+        <parameter value="lon_0=50.76138888888889"/>
+        <parameter value="x_0=100000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2100" name="GGRS87 / Greek Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=-199.87,74.79,246.62,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2101" name="Lake / Maracaibo Grid M1">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=10.16666666666667"/>
+        <parameter value="lat_0=10.16666666666667"/>
+        <parameter value="lon_0=-71.60561777777777"/>
+        <parameter value="k_0=1"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=-52684.972"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2102" name="Lake / Maracaibo Grid">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=10.16666666666667"/>
+        <parameter value="lat_0=10.16666666666667"/>
+        <parameter value="lon_0=-71.60561777777777"/>
+        <parameter value="k_0=1"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=147315.028"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2103" name="Lake / Maracaibo Grid M3">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=10.16666666666667"/>
+        <parameter value="lat_0=10.16666666666667"/>
+        <parameter value="lon_0=-71.60561777777777"/>
+        <parameter value="k_0=1"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=447315.028"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2104" name="Lake / Maracaibo La Rosa Grid">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=10.16666666666667"/>
+        <parameter value="lat_0=10.16666666666667"/>
+        <parameter value="lon_0=-71.60561777777777"/>
+        <parameter value="k_0=1"/>
+        <parameter value="x_0=-17044"/>
+        <parameter value="y_0=-23139.97"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2105" name="NZGD2000 / Mount Eden Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-36.87972222222222"/>
+        <parameter value="lon_0=174.7641666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2106" name="NZGD2000 / Bay of Plenty Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-37.76111111111111"/>
+        <parameter value="lon_0=176.4661111111111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2107" name="NZGD2000 / Poverty Bay Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-38.62444444444444"/>
+        <parameter value="lon_0=177.8855555555556"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2108" name="NZGD2000 / Hawkes Bay Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-39.65083333333333"/>
+        <parameter value="lon_0=176.6736111111111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2109" name="NZGD2000 / Taranaki Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-39.13555555555556"/>
+        <parameter value="lon_0=174.2277777777778"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2110" name="NZGD2000 / Tuhirangi Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-39.51222222222222"/>
+        <parameter value="lon_0=175.64"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2111" name="NZGD2000 / Wanganui Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-40.24194444444444"/>
+        <parameter value="lon_0=175.4880555555555"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2112" name="NZGD2000 / Wairarapa Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-40.92527777777777"/>
+        <parameter value="lon_0=175.6472222222222"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2113" name="NZGD2000 / Wellington Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-41.3011111111111"/>
+        <parameter value="lon_0=174.7763888888889"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2114" name="NZGD2000 / Collingwood Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-40.71472222222223"/>
+        <parameter value="lon_0=172.6719444444444"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2115" name="NZGD2000 / Nelson Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-41.27444444444444"/>
+        <parameter value="lon_0=173.2991666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2116" name="NZGD2000 / Karamea Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-41.28972222222222"/>
+        <parameter value="lon_0=172.1088888888889"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2117" name="NZGD2000 / Buller Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-41.81055555555555"/>
+        <parameter value="lon_0=171.5811111111111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2118" name="NZGD2000 / Grey Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-42.33361111111111"/>
+        <parameter value="lon_0=171.5497222222222"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2119" name="NZGD2000 / Amuri Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-42.68888888888888"/>
+        <parameter value="lon_0=173.01"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2120" name="NZGD2000 / Marlborough Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-41.54444444444444"/>
+        <parameter value="lon_0=173.8019444444444"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2121" name="NZGD2000 / Hokitika Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-42.88611111111111"/>
+        <parameter value="lon_0=170.9797222222222"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2122" name="NZGD2000 / Okarito Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-43.11"/>
+        <parameter value="lon_0=170.2608333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2123" name="NZGD2000 / Jacksons Bay Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-43.97777777777778"/>
+        <parameter value="lon_0=168.6061111111111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2124" name="NZGD2000 / Mount Pleasant Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-43.59055555555556"/>
+        <parameter value="lon_0=172.7269444444445"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2125" name="NZGD2000 / Gawler Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-43.74861111111111"/>
+        <parameter value="lon_0=171.3605555555555"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2126" name="NZGD2000 / Timaru Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-44.40194444444445"/>
+        <parameter value="lon_0=171.0572222222222"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2127" name="NZGD2000 / Lindis Peak Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-44.735"/>
+        <parameter value="lon_0=169.4675"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2128" name="NZGD2000 / Mount Nicholas Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-45.13277777777778"/>
+        <parameter value="lon_0=168.3986111111111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2129" name="NZGD2000 / Mount York Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-45.56361111111111"/>
+        <parameter value="lon_0=167.7386111111111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2130" name="NZGD2000 / Observation Point Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-45.81611111111111"/>
+        <parameter value="lon_0=170.6283333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2131" name="NZGD2000 / North Taieri Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-45.86138888888889"/>
+        <parameter value="lon_0=170.2825"/>
+        <parameter value="k=0.999960"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2132" name="NZGD2000 / Bluff Circuit 2000">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-46.6"/>
+        <parameter value="lon_0=168.3427777777778"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2133" name="NZGD2000 / UTM zone 58S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2134" name="NZGD2000 / UTM zone 59S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=59"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2135" name="NZGD2000 / UTM zone 60S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=60"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2136" name="Accra / Ghana National Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=4.666666666666667"/>
+        <parameter value="lon_0=-1"/>
+        <parameter value="k=0.999750"/>
+        <parameter value="x_0=274319.7391633579"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378300"/>
+        <parameter value="b=6356751.689189189"/>
+        <parameter value="towgs84=-199,32,322,0,0,0,0"/>
+        <parameter value="to_meter=0.3047997101815088"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2137" name="Accra / TM 1 NW">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-1"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378300"/>
+        <parameter value="b=6356751.689189189"/>
+        <parameter value="towgs84=-199,32,322,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2138" name="NAD27(CGQ77) / Quebec Lambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=60"/>
+        <parameter value="lat_2=46"/>
+        <parameter value="lat_0=44"/>
+        <parameter value="lon_0=-68.5"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2139" name="NAD83(CSRS98) / SCoPQ zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-55.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2140" name="NAD83(CSRS98) / MTM zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-58.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2141" name="NAD83(CSRS98) / MTM zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-61.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2142" name="NAD83(CSRS98) / MTM zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-64.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2143" name="NAD83(CSRS98) / MTM zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-67.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2144" name="NAD83(CSRS98) / MTM zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-70.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2145" name="NAD83(CSRS98) / MTM zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-73.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2146" name="NAD83(CSRS98) / MTM zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-76.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2147" name="NAD83(CSRS98) / MTM zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-79.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2148" name="NAD83(CSRS98) / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2149" name="NAD83(CSRS98) / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2150" name="NAD83(CSRS98) / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2151" name="NAD83(CSRS98) / UTM zone 13N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=13"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2152" name="NAD83(CSRS98) / UTM zone 12N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=12"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2153" name="NAD83(CSRS98) / UTM zone 11N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=11"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2154" name="RGF93 / Lambert-93">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49"/>
+        <parameter value="lat_2=44"/>
+        <parameter value="lat_0=46.5"/>
+        <parameter value="lon_0=3"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=6600000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2155" name="American Samoa 1962 / American Samoa Lambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=-14.26666666666667"/>
+        <parameter value="lat_0=-14.26666666666667"/>
+        <parameter value="lon_0=170"/>
+        <parameter value="k_0=1"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="towgs84=-115,118,426,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2156" name="NAD83(HARN) / UTM zone 59S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=59"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2157" name="IRENET95 / Irish Transverse Mercator">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=53.5"/>
+        <parameter value="lon_0=-8"/>
+        <parameter value="k=0.999820"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=750000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2158" name="IRENET95 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2159" name="Sierra Leone 1924 / New Colony Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=6.666666666666667"/>
+        <parameter value="lon_0=-12"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=152399.8550907544"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378300"/>
+        <parameter value="b=6356751.689189189"/>
+        <parameter value="to_meter=0.3047997101815088"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2160" name="Sierra Leone 1924 / New War Office Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=6.666666666666667"/>
+        <parameter value="lon_0=-12"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=243839.7681452071"/>
+        <parameter value="y_0=182879.8261089053"/>
+        <parameter value="a=6378300"/>
+        <parameter value="b=6356751.689189189"/>
+        <parameter value="to_meter=0.3047997101815088"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2161" name="Sierra Leone 1968 / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-88,4,101,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2162" name="Sierra Leone 1968 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-88,4,101,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2163" name="US National Atlas Equal Area">
+        <parameter value="proj=laea"/>
+        <parameter value="lat_0=45"/>
+        <parameter value="lon_0=-100"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6370997"/>
+        <parameter value="b=6370997"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2164" name="Locodjo 1965 / TM 5 NW">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-5"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-125,53,467,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2165" name="Abidjan 1987 / TM 5 NW">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-5"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-124.76,53,466.79,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2166" name="Pulkovo 1942(83) / Gauss Kruger zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=9"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=24,-123,-94,0.02,-0.25,-0.13,1.1"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2167" name="Pulkovo 1942(83) / Gauss Kruger zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=12"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=24,-123,-94,0.02,-0.25,-0.13,1.1"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2168" name="Pulkovo 1942(83) / Gauss Kruger zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=24,-123,-94,0.02,-0.25,-0.13,1.1"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2169" name="Luxembourg 1930 / Gauss">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=49.83333333333334"/>
+        <parameter value="lon_0=6.166666666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=80000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-193,13.7,-39.3,-0.41,-2.933,2.688,0.43"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2170" name="MGI / Slovenia Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2171" name="Pulkovo 1942(58) / Poland zone I">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=50.625"/>
+        <parameter value="lon_0=21.08333333333333"/>
+        <parameter value="k=0.999800"/>
+        <parameter value="x_0=4637000"/>
+        <parameter value="y_0=5647000"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2172" name="Pulkovo 1942(58) / Poland zone II">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=53.00194444444445"/>
+        <parameter value="lon_0=21.50277777777778"/>
+        <parameter value="k=0.999800"/>
+        <parameter value="x_0=4603000"/>
+        <parameter value="y_0=5806000"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2173" name="Pulkovo 1942(58) / Poland zone III">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=53.58333333333334"/>
+        <parameter value="lon_0=17.00833333333333"/>
+        <parameter value="k=0.999800"/>
+        <parameter value="x_0=3501000"/>
+        <parameter value="y_0=5999000"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2174" name="Pulkovo 1942(58) / Poland zone IV">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=51.67083333333333"/>
+        <parameter value="lon_0=16.67222222222222"/>
+        <parameter value="k=0.999800"/>
+        <parameter value="x_0=3703000"/>
+        <parameter value="y_0=5627000"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2175" name="Pulkovo 1942(58) / Poland zone V">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=18.95833333333333"/>
+        <parameter value="k=0.999983"/>
+        <parameter value="x_0=237000"/>
+        <parameter value="y_0=-4700000"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2176" name="ETRS89 / Poland CS2000 zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=0.999923"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2177" name="ETRS89 / Poland CS2000 zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=18"/>
+        <parameter value="k=0.999923"/>
+        <parameter value="x_0=6500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2178" name="ETRS89 / Poland CS2000 zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=0.999923"/>
+        <parameter value="x_0=7500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2179" name="ETRS89 / Poland CS2000 zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=0.999923"/>
+        <parameter value="x_0=8500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2180" name="ETRS89 / Poland CS92">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=19"/>
+        <parameter value="k=0.999300"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=-5300000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2188" name="Azores Occidental 1939 / UTM zone 25N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=25"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2189" name="Azores Central 1948 / UTM zone 26N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=26"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2190" name="Azores Oriental 1940 / UTM zone 26N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=26"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2191" name="Madeira 1936 / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2192" name="ED50 / France EuroLambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.8"/>
+        <parameter value="lat_0=46.8"/>
+        <parameter value="lon_0=2.337229166666667"/>
+        <parameter value="k_0=0.99987742"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=2200000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2193" name="NZGD2000 / New Zealand Transverse Mercator">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=173"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=1600000"/>
+        <parameter value="y_0=10000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2194" name="American Samoa 1962 / American Samoa Lambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=-14.26666666666667"/>
+        <parameter value="lat_0=-14.26666666666667"/>
+        <parameter value="lon_0=-170"/>
+        <parameter value="k_0=1"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="towgs84=-115,118,426,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2195" name="NAD83(HARN) / UTM zone 2S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=2"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2196" name="ETRS89 / Kp2000 Jutland">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=9.5"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2197" name="ETRS89 / Kp2000 Zealand">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=12"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2198" name="ETRS89 / Kp2000 Bornholm">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=900000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2199" name="Albanian 1987 / Gauss Kruger zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2200" name="ATS77 / New Brunswick Stereographic (ATS77)">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=46.5"/>
+        <parameter value="lon_0=-66.5"/>
+        <parameter value="k=0.999912"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="a=6378135"/>
+        <parameter value="b=6356750.304921594"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2201" name="REGVEN / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2202" name="REGVEN / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2203" name="REGVEN / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2204" name="NAD27 / Tennessee">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.25"/>
+        <parameter value="lat_2=36.41666666666666"/>
+        <parameter value="lat_0=34.66666666666666"/>
+        <parameter value="lon_0=-86"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=30480.06096012192"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2205" name="NAD83 / Kentucky North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.96666666666667"/>
+        <parameter value="lat_2=38.96666666666667"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-84.25"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2206" name="ED50 / 3-degree Gauss-Kruger zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=9500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2207" name="ED50 / 3-degree Gauss-Kruger zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=30"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=10500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2208" name="ED50 / 3-degree Gauss-Kruger zone 11">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=11500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2209" name="ED50 / 3-degree Gauss-Kruger zone 12">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=36"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=12500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2210" name="ED50 / 3-degree Gauss-Kruger zone 13">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=13500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2211" name="ED50 / 3-degree Gauss-Kruger zone 14">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=42"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=14500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2212" name="ED50 / 3-degree Gauss-Kruger zone 15">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=15500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2213" name="ETRS89 / TM 30 NE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=30"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2214" name="Douala 1948 / AOF west">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=10.5"/>
+        <parameter value="k=0.999000"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2215" name="Manoca 1962 / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-70.9,-151.8,-41.4,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2216" name="Qornoq 1927 / UTM zone 22N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2217" name="Qornoq 1927 / UTM zone 23N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2219" name="ATS77 / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="a=6378135"/>
+        <parameter value="b=6356750.304921594"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2220" name="ATS77 / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="a=6378135"/>
+        <parameter value="b=6356750.304921594"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2222" name="NAD83 / Arizona East (ft)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-110.1666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2223" name="NAD83 / Arizona Central (ft)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-111.9166666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2224" name="NAD83 / Arizona West (ft)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-113.75"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2225" name="NAD83 / California zone 1 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.66666666666666"/>
+        <parameter value="lat_2=40"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-122"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2226" name="NAD83 / California zone 2 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.83333333333334"/>
+        <parameter value="lat_2=38.33333333333334"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-122"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2227" name="NAD83 / California zone 3 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.43333333333333"/>
+        <parameter value="lat_2=37.06666666666667"/>
+        <parameter value="lat_0=36.5"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2228" name="NAD83 / California zone 4 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.25"/>
+        <parameter value="lat_2=36"/>
+        <parameter value="lat_0=35.33333333333334"/>
+        <parameter value="lon_0=-119"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2229" name="NAD83 / California zone 5 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.46666666666667"/>
+        <parameter value="lat_2=34.03333333333333"/>
+        <parameter value="lat_0=33.5"/>
+        <parameter value="lon_0=-118"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2230" name="NAD83 / California zone 6 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.88333333333333"/>
+        <parameter value="lat_2=32.78333333333333"/>
+        <parameter value="lat_0=32.16666666666666"/>
+        <parameter value="lon_0=-116.25"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2231" name="NAD83 / Colorado North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.78333333333333"/>
+        <parameter value="lat_2=39.71666666666667"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8288036576"/>
+        <parameter value="y_0=304800.6096012192"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2232" name="NAD83 / Colorado Central (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.75"/>
+        <parameter value="lat_2=38.45"/>
+        <parameter value="lat_0=37.83333333333334"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8288036576"/>
+        <parameter value="y_0=304800.6096012192"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2233" name="NAD83 / Colorado South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.43333333333333"/>
+        <parameter value="lat_2=37.23333333333333"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8288036576"/>
+        <parameter value="y_0=304800.6096012192"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2234" name="NAD83 / Connecticut (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.86666666666667"/>
+        <parameter value="lat_2=41.2"/>
+        <parameter value="lat_0=40.83333333333334"/>
+        <parameter value="lon_0=-72.75"/>
+        <parameter value="x_0=304800.6096012192"/>
+        <parameter value="y_0=152400.3048006096"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2235" name="NAD83 / Delaware (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=-75.41666666666667"/>
+        <parameter value="k=0.999995"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2236" name="NAD83 / Florida East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.33333333333333"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2237" name="NAD83 / Florida West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.33333333333333"/>
+        <parameter value="lon_0=-82"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2238" name="NAD83 / Florida North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.75"/>
+        <parameter value="lat_2=29.58333333333333"/>
+        <parameter value="lat_0=29"/>
+        <parameter value="lon_0=-84.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2239" name="NAD83 / Georgia East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-82.16666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2240" name="NAD83 / Georgia West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-84.16666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=699999.9998983998"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2241" name="NAD83 / Idaho East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-112.1666666666667"/>
+        <parameter value="k=0.999947"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2242" name="NAD83 / Idaho Central (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-114"/>
+        <parameter value="k=0.999947"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2243" name="NAD83 / Idaho West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-115.75"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=800000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2244" name="NAD83 / Indiana East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-85.66666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=99999.99989839978"/>
+        <parameter value="y_0=249364.9987299975"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2245" name="NAD83 / Indiana West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-87.08333333333333"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=900000"/>
+        <parameter value="y_0=249364.9987299975"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2246" name="NAD83 / Kentucky North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.96666666666667"/>
+        <parameter value="lat_2=38.96666666666667"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-84.25"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2247" name="NAD83 / Kentucky South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.93333333333333"/>
+        <parameter value="lat_2=36.73333333333333"/>
+        <parameter value="lat_0=36.33333333333334"/>
+        <parameter value="lon_0=-85.75"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2248" name="NAD83 / Maryland (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.45"/>
+        <parameter value="lat_2=38.3"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-77"/>
+        <parameter value="x_0=399999.9998983998"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2249" name="NAD83 / Massachusetts Mainland (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.68333333333333"/>
+        <parameter value="lat_2=41.71666666666667"/>
+        <parameter value="lat_0=41"/>
+        <parameter value="lon_0=-71.5"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=750000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2250" name="NAD83 / Massachusetts Island (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.48333333333333"/>
+        <parameter value="lat_2=41.28333333333333"/>
+        <parameter value="lat_0=41"/>
+        <parameter value="lon_0=-70.5"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2251" name="NAD83 / Michigan North (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.08333333333334"/>
+        <parameter value="lat_2=45.48333333333333"/>
+        <parameter value="lat_0=44.78333333333333"/>
+        <parameter value="lon_0=-87"/>
+        <parameter value="x_0=7999999.999968001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2252" name="NAD83 / Michigan Central (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.7"/>
+        <parameter value="lat_2=44.18333333333333"/>
+        <parameter value="lat_0=43.31666666666667"/>
+        <parameter value="lon_0=-84.36666666666666"/>
+        <parameter value="x_0=5999999.999976001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2253" name="NAD83 / Michigan South (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=43.66666666666666"/>
+        <parameter value="lat_2=42.1"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-84.36666666666666"/>
+        <parameter value="x_0=3999999.999984"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2254" name="NAD83 / Mississippi East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=29.5"/>
+        <parameter value="lon_0=-88.83333333333333"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=300000.0000000001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2255" name="NAD83 / Mississippi West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=29.5"/>
+        <parameter value="lon_0=-90.33333333333333"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=699999.9998983998"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2256" name="NAD83 / Montana (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49"/>
+        <parameter value="lat_2=45"/>
+        <parameter value="lat_0=44.25"/>
+        <parameter value="lon_0=-109.5"/>
+        <parameter value="x_0=599999.9999976"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2257" name="NAD83 / New Mexico East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-104.3333333333333"/>
+        <parameter value="k=0.999909"/>
+        <parameter value="x_0=165000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2258" name="NAD83 / New Mexico Central (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-106.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2259" name="NAD83 / New Mexico West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-107.8333333333333"/>
+        <parameter value="k=0.999917"/>
+        <parameter value="x_0=830000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2260" name="NAD83 / New York East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38.83333333333334"/>
+        <parameter value="lon_0=-74.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=150000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2261" name="NAD83 / New York Central (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-76.58333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=249999.9998983998"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2262" name="NAD83 / New York West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-78.58333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=350000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2263" name="NAD83 / New York Long Island (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.03333333333333"/>
+        <parameter value="lat_2=40.66666666666666"/>
+        <parameter value="lat_0=40.16666666666666"/>
+        <parameter value="lon_0=-74"/>
+        <parameter value="x_0=300000.0000000001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2264" name="NAD83 / North Carolina (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.16666666666666"/>
+        <parameter value="lat_2=34.33333333333334"/>
+        <parameter value="lat_0=33.75"/>
+        <parameter value="lon_0=-79"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2265" name="NAD83 / North Dakota North (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.73333333333333"/>
+        <parameter value="lat_2=47.43333333333333"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-100.5"/>
+        <parameter value="x_0=599999.9999976"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2266" name="NAD83 / North Dakota South (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.48333333333333"/>
+        <parameter value="lat_2=46.18333333333333"/>
+        <parameter value="lat_0=45.66666666666666"/>
+        <parameter value="lon_0=-100.5"/>
+        <parameter value="x_0=599999.9999976"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2267" name="NAD83 / Oklahoma North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.76666666666667"/>
+        <parameter value="lat_2=35.56666666666667"/>
+        <parameter value="lat_0=35"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2268" name="NAD83 / Oklahoma South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.23333333333333"/>
+        <parameter value="lat_2=33.93333333333333"/>
+        <parameter value="lat_0=33.33333333333334"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2269" name="NAD83 / Oregon North (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46"/>
+        <parameter value="lat_2=44.33333333333334"/>
+        <parameter value="lat_0=43.66666666666666"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=2500000.0001424"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2270" name="NAD83 / Oregon South (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44"/>
+        <parameter value="lat_2=42.33333333333334"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=1500000.0001464"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2271" name="NAD83 / Pennsylvania North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.95"/>
+        <parameter value="lat_2=40.88333333333333"/>
+        <parameter value="lat_0=40.16666666666666"/>
+        <parameter value="lon_0=-77.75"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2272" name="NAD83 / Pennsylvania South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.96666666666667"/>
+        <parameter value="lat_2=39.93333333333333"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-77.75"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2273" name="NAD83 / South Carolina (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=34.83333333333334"/>
+        <parameter value="lat_2=32.5"/>
+        <parameter value="lat_0=31.83333333333333"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="x_0=609600"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2274" name="NAD83 / Tennessee (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.41666666666666"/>
+        <parameter value="lat_2=35.25"/>
+        <parameter value="lat_0=34.33333333333334"/>
+        <parameter value="lon_0=-86"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2275" name="NAD83 / Texas North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.18333333333333"/>
+        <parameter value="lat_2=34.65"/>
+        <parameter value="lat_0=34"/>
+        <parameter value="lon_0=-101.5"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=999999.9998983998"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2276" name="NAD83 / Texas North Central (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.96666666666667"/>
+        <parameter value="lat_2=32.13333333333333"/>
+        <parameter value="lat_0=31.66666666666667"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=2000000.0001016"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2277" name="NAD83 / Texas Central (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=31.88333333333333"/>
+        <parameter value="lat_2=30.11666666666667"/>
+        <parameter value="lat_0=29.66666666666667"/>
+        <parameter value="lon_0=-100.3333333333333"/>
+        <parameter value="x_0=699999.9998983998"/>
+        <parameter value="y_0=3000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2278" name="NAD83 / Texas South Central (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.28333333333333"/>
+        <parameter value="lat_2=28.38333333333333"/>
+        <parameter value="lat_0=27.83333333333333"/>
+        <parameter value="lon_0=-99"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=3999999.9998984"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2279" name="NAD83 / Texas South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=27.83333333333333"/>
+        <parameter value="lat_2=26.16666666666667"/>
+        <parameter value="lat_0=25.66666666666667"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=300000.0000000001"/>
+        <parameter value="y_0=5000000.0001016"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2280" name="NAD83 / Utah North (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.78333333333333"/>
+        <parameter value="lat_2=40.71666666666667"/>
+        <parameter value="lat_0=40.33333333333334"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000.0001504"/>
+        <parameter value="y_0=999999.9999960001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2281" name="NAD83 / Utah Central (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.65"/>
+        <parameter value="lat_2=39.01666666666667"/>
+        <parameter value="lat_0=38.33333333333334"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000.0001504"/>
+        <parameter value="y_0=1999999.999992"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2282" name="NAD83 / Utah South (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.35"/>
+        <parameter value="lat_2=37.21666666666667"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000.0001504"/>
+        <parameter value="y_0=2999999.999988"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2283" name="NAD83 / Virginia North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.2"/>
+        <parameter value="lat_2=38.03333333333333"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-78.5"/>
+        <parameter value="x_0=3500000.0001016"/>
+        <parameter value="y_0=2000000.0001016"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2284" name="NAD83 / Virginia South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.96666666666667"/>
+        <parameter value="lat_2=36.76666666666667"/>
+        <parameter value="lat_0=36.33333333333334"/>
+        <parameter value="lon_0=-78.5"/>
+        <parameter value="x_0=3500000.0001016"/>
+        <parameter value="y_0=999999.9998983998"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2285" name="NAD83 / Washington North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.73333333333333"/>
+        <parameter value="lat_2=47.5"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-120.8333333333333"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2286" name="NAD83 / Washington South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.33333333333334"/>
+        <parameter value="lat_2=45.83333333333334"/>
+        <parameter value="lat_0=45.33333333333334"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2287" name="NAD83 / Wisconsin North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.76666666666667"/>
+        <parameter value="lat_2=45.56666666666667"/>
+        <parameter value="lat_0=45.16666666666666"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2288" name="NAD83 / Wisconsin Central (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.5"/>
+        <parameter value="lat_2=44.25"/>
+        <parameter value="lat_0=43.83333333333334"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2289" name="NAD83 / Wisconsin South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.06666666666667"/>
+        <parameter value="lat_2=42.73333333333333"/>
+        <parameter value="lat_0=42"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2290" name="ATS77 / Prince Edward Isl. Stereographic (ATS77)">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=47.25"/>
+        <parameter value="lon_0=-63"/>
+        <parameter value="k=0.999912"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=400000"/>
+        <parameter value="a=6378135"/>
+        <parameter value="b=6356750.304921594"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2291" name="NAD83(CSRS98) / Prince Edward Isl. Stereographic (NAD83)">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=47.25"/>
+        <parameter value="lon_0=-63"/>
+        <parameter value="k=0.999912"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="a=6378135"/>
+        <parameter value="b=6356750.304921594"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2292" name="NAD83(CSRS98) / Prince Edward Isl. Stereographic (NAD83)">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=47.25"/>
+        <parameter value="lon_0=-63"/>
+        <parameter value="k=0.999912"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2294" name="ATS77 / MTM Nova Scotia zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-61.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378135"/>
+        <parameter value="b=6356750.304921594"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2295" name="ATS77 / MTM Nova Scotia zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-64.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378135"/>
+        <parameter value="b=6356750.304921594"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2308" name="Batavia / TM 109 SE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=109"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=10000000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2309" name="WGS 84 / TM 116 SE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=116"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=10000000"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2310" name="WGS 84 / TM 132 SE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=132"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=10000000"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2311" name="WGS 84 / TM 6 NE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=6"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2312" name="Garoua / UTM zone 33N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2313" name="Kousseri / UTM zone 33N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2314" name="Trinidad 1903 / Trinidad Grid (ftCla)">
+        <parameter value="proj=cass"/>
+        <parameter value="lat_0=10.44166666666667"/>
+        <parameter value="lon_0=-61.33333333333334"/>
+        <parameter value="x_0=86501.46380699999"/>
+        <parameter value="y_0=65379.01334249999"/>
+        <parameter value="a=6378293.63683822"/>
+        <parameter value="b=6356617.979337744"/>
+        <parameter value="towgs84=-61.702,284.488,472.052,0,0,0,0"/>
+        <parameter value="to_meter=0.304797265"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2315" name="Campo Inchauspe / UTM zone 19S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2316" name="Campo Inchauspe / UTM zone 20S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2317" name="PSAD56 / ICN Regional">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=9"/>
+        <parameter value="lat_2=3"/>
+        <parameter value="lat_0=6"/>
+        <parameter value="lon_0=-66"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2318" name="Ain el Abd / Aramco Lambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=17"/>
+        <parameter value="lat_2=33"/>
+        <parameter value="lat_0=25.08951"/>
+        <parameter value="lon_0=48"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2319" name="ED50 / TM27">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2320" name="ED50 / TM30">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=30"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2321" name="ED50 / TM33">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2322" name="ED50 / TM36">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=36"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2323" name="ED50 / TM39">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2324" name="ED50 / TM42">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=42"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2325" name="ED50 / TM45">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2326" name="Hong Kong 1980 Grid System">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=22.31213333333334"/>
+        <parameter value="lon_0=114.1785555555556"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=836694.05"/>
+        <parameter value="y_0=819069.8"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-162.619,-276.959,-161.764,0.067753,-2.24365,-1.15883,-1.09425"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2327" name="Xian 1980 / Gauss-Kruger zone 13">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=13500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2328" name="Xian 1980 / Gauss-Kruger zone 14">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=14500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2329" name="Xian 1980 / Gauss-Kruger zone 15">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=15500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2330" name="Xian 1980 / Gauss-Kruger zone 16">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=16500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2331" name="Xian 1980 / Gauss-Kruger zone 17">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=17500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2332" name="Xian 1980 / Gauss-Kruger zone 18">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=18500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2333" name="Xian 1980 / Gauss-Kruger zone 19">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=19500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2334" name="Xian 1980 / Gauss-Kruger zone 20">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=20500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2335" name="Xian 1980 / Gauss-Kruger zone 21">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=21500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2336" name="Xian 1980 / Gauss-Kruger zone 22">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=22500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2337" name="Xian 1980 / Gauss-Kruger zone 23">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=23500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2338" name="Xian 1980 / Gauss-Kruger CM 75E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2339" name="Xian 1980 / Gauss-Kruger CM 81E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2340" name="Xian 1980 / Gauss-Kruger CM 87E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2341" name="Xian 1980 / Gauss-Kruger CM 93E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2342" name="Xian 1980 / Gauss-Kruger CM 99E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2343" name="Xian 1980 / Gauss-Kruger CM 105E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2344" name="Xian 1980 / Gauss-Kruger CM 111E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2345" name="Xian 1980 / Gauss-Kruger CM 117E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2346" name="Xian 1980 / Gauss-Kruger CM 123E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2347" name="Xian 1980 / Gauss-Kruger CM 129E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2348" name="Xian 1980 / Gauss-Kruger CM 135E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2349" name="Xian 1980 / 3-degree Gauss-Kruger zone 25">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=25500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2350" name="Xian 1980 / 3-degree Gauss-Kruger zone 26">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=78"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=26500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2351" name="Xian 1980 / 3-degree Gauss-Kruger zone 27">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=27500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2352" name="Xian 1980 / 3-degree Gauss-Kruger zone 28">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=84"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=28500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2353" name="Xian 1980 / 3-degree Gauss-Kruger zone 29">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=29500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2354" name="Xian 1980 / 3-degree Gauss-Kruger zone 30">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=30500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2355" name="Xian 1980 / 3-degree Gauss-Kruger zone 31">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=31500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2356" name="Xian 1980 / 3-degree Gauss-Kruger zone 32">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=96"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=32500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2357" name="Xian 1980 / 3-degree Gauss-Kruger zone 33">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=33500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2358" name="Xian 1980 / 3-degree Gauss-Kruger zone 34">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=102"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=34500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2359" name="Xian 1980 / 3-degree Gauss-Kruger zone 35">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=35500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2360" name="Xian 1980 / 3-degree Gauss-Kruger zone 36">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=108"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=36500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2361" name="Xian 1980 / 3-degree Gauss-Kruger zone 37">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=37500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2362" name="Xian 1980 / 3-degree Gauss-Kruger zone 38">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=114"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=38500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2363" name="Xian 1980 / 3-degree Gauss-Kruger zone 39">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=39500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2364" name="Xian 1980 / 3-degree Gauss-Kruger zone 40">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=120"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=40500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2365" name="Xian 1980 / 3-degree Gauss-Kruger zone 41">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=41500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2366" name="Xian 1980 / 3-degree Gauss-Kruger zone 42">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=126"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=42500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2367" name="Xian 1980 / 3-degree Gauss-Kruger zone 43">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=43500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2368" name="Xian 1980 / 3-degree Gauss-Kruger zone 44">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=132"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=44500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2369" name="Xian 1980 / 3-degree Gauss-Kruger zone 45">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=45500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2370" name="Xian 1980 / 3-degree Gauss-Kruger CM 75E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2371" name="Xian 1980 / 3-degree Gauss-Kruger CM 78E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=78"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2372" name="Xian 1980 / 3-degree Gauss-Kruger CM 81E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2373" name="Xian 1980 / 3-degree Gauss-Kruger CM 84E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=84"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2374" name="Xian 1980 / 3-degree Gauss-Kruger CM 87E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2375" name="Xian 1980 / 3-degree Gauss-Kruger CM 90E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2376" name="Xian 1980 / 3-degree Gauss-Kruger CM 93E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2377" name="Xian 1980 / 3-degree Gauss-Kruger CM 96E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=96"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2378" name="Xian 1980 / 3-degree Gauss-Kruger CM 99E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2379" name="Xian 1980 / 3-degree Gauss-Kruger CM 102E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=102"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2380" name="Xian 1980 / 3-degree Gauss-Kruger CM 105E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2381" name="Xian 1980 / 3-degree Gauss-Kruger CM 108E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=108"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2382" name="Xian 1980 / 3-degree Gauss-Kruger CM 111E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2383" name="Xian 1980 / 3-degree Gauss-Kruger CM 114E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=114"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2384" name="Xian 1980 / 3-degree Gauss-Kruger CM 117E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2385" name="Xian 1980 / 3-degree Gauss-Kruger CM 120E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=120"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2386" name="Xian 1980 / 3-degree Gauss-Kruger CM 123E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2387" name="Xian 1980 / 3-degree Gauss-Kruger CM 126E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=126"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2388" name="Xian 1980 / 3-degree Gauss-Kruger CM 129E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2389" name="Xian 1980 / 3-degree Gauss-Kruger CM 132E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=132"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2390" name="Xian 1980 / 3-degree Gauss-Kruger CM 135E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2391" name="KKJ / Finland zone 1">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-90.7,-106.1,-119.2,4.09,0.218,-1.05,1.37"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2392" name="KKJ / Finland zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-90.7,-106.1,-119.2,4.09,0.218,-1.05,1.37"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2393" name="KKJ / Finland Uniform Coordinate System">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-90.7,-106.1,-119.2,4.09,0.218,-1.05,1.37"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2394" name="KKJ / Finland zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=30"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-90.7,-106.1,-119.2,4.09,0.218,-1.05,1.37"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2395" name="South Yemen / Gauss-Kruger zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=8500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-76,-138,67,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2396" name="South Yemen / Gauss-Kruger zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=9500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-76,-138,67,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2397" name="Pulkovo 1942(83) / Gauss-Kruger zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=9"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=24,-123,-94,0.02,-0.25,-0.13,1.1"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2398" name="Pulkovo 1942(83) / Gauss-Kruger zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=12"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=24,-123,-94,0.02,-0.25,-0.13,1.1"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2399" name="Pulkovo 1942(83) / Gauss-Kruger zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=24,-123,-94,0.02,-0.25,-0.13,1.1"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2400" name="RT90 2.5 gon W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15.80827777777778"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2401" name="Beijing 1954 / 3-degree Gauss-Kruger zone 25">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=25500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2402" name="Beijing 1954 / 3-degree Gauss-Kruger zone 26">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=78"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=26500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2403" name="Beijing 1954 / 3-degree Gauss-Kruger zone 27">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=27500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2404" name="Beijing 1954 / 3-degree Gauss-Kruger zone 28">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=84"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=28500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2405" name="Beijing 1954 / 3-degree Gauss-Kruger zone 29">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=29500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2406" name="Beijing 1954 / 3-degree Gauss-Kruger zone 30">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=30500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2407" name="Beijing 1954 / 3-degree Gauss-Kruger zone 31">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=31500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2408" name="Beijing 1954 / 3-degree Gauss-Kruger zone 32">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=96"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=32500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2409" name="Beijing 1954 / 3-degree Gauss-Kruger zone 33">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=33500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2410" name="Beijing 1954 / 3-degree Gauss-Kruger zone 34">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=102"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=34500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2411" name="Beijing 1954 / 3-degree Gauss-Kruger zone 35">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=35500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2412" name="Beijing 1954 / 3-degree Gauss-Kruger zone 36">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=108"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=36500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2413" name="Beijing 1954 / 3-degree Gauss-Kruger zone 37">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=37500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2414" name="Beijing 1954 / 3-degree Gauss-Kruger zone 38">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=114"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=38500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2415" name="Beijing 1954 / 3-degree Gauss-Kruger zone 39">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=39500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2416" name="Beijing 1954 / 3-degree Gauss-Kruger zone 40">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=120"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=40500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2417" name="Beijing 1954 / 3-degree Gauss-Kruger zone 41">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=41500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2418" name="Beijing 1954 / 3-degree Gauss-Kruger zone 42">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=126"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=42500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2419" name="Beijing 1954 / 3-degree Gauss-Kruger zone 43">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=43500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2420" name="Beijing 1954 / 3-degree Gauss-Kruger zone 44">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=132"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=44500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2421" name="Beijing 1954 / 3-degree Gauss-Kruger zone 45">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=45500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2422" name="Beijing 1954 / 3-degree Gauss-Kruger CM 75E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2423" name="Beijing 1954 / 3-degree Gauss-Kruger CM 78E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=78"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2424" name="Beijing 1954 / 3-degree Gauss-Kruger CM 81E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2425" name="Beijing 1954 / 3-degree Gauss-Kruger CM 84E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=84"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2426" name="Beijing 1954 / 3-degree Gauss-Kruger CM 87E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2427" name="Beijing 1954 / 3-degree Gauss-Kruger CM 90E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2428" name="Beijing 1954 / 3-degree Gauss-Kruger CM 93E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2429" name="Beijing 1954 / 3-degree Gauss-Kruger CM 96E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=96"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2430" name="Beijing 1954 / 3-degree Gauss-Kruger CM 99E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2431" name="Beijing 1954 / 3-degree Gauss-Kruger CM 102E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=102"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2432" name="Beijing 1954 / 3-degree Gauss-Kruger CM 105E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2433" name="Beijing 1954 / 3-degree Gauss-Kruger CM 108E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=108"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2434" name="Beijing 1954 / 3-degree Gauss-Kruger CM 111E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2435" name="Beijing 1954 / 3-degree Gauss-Kruger CM 114E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=114"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2436" name="Beijing 1954 / 3-degree Gauss-Kruger CM 117E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2437" name="Beijing 1954 / 3-degree Gauss-Kruger CM 120E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=120"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2438" name="Beijing 1954 / 3-degree Gauss-Kruger CM 123E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2439" name="Beijing 1954 / 3-degree Gauss-Kruger CM 126E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=126"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2440" name="Beijing 1954 / 3-degree Gauss-Kruger CM 129E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2441" name="Beijing 1954 / 3-degree Gauss-Kruger CM 132E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=132"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2442" name="Beijing 1954 / 3-degree Gauss-Kruger CM 135E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2443" name="JGD2000 / Japan Plane Rectangular CS I">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=33"/>
+        <parameter value="lon_0=129.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2444" name="JGD2000 / Japan Plane Rectangular CS II">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=33"/>
+        <parameter value="lon_0=131"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2445" name="JGD2000 / Japan Plane Rectangular CS III">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=132.1666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2446" name="JGD2000 / Japan Plane Rectangular CS IV">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=33"/>
+        <parameter value="lon_0=133.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2447" name="JGD2000 / Japan Plane Rectangular CS V">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=134.3333333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2448" name="JGD2000 / Japan Plane Rectangular CS VI">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=136"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2449" name="JGD2000 / Japan Plane Rectangular CS VII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=137.1666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2450" name="JGD2000 / Japan Plane Rectangular CS VIII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=138.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2451" name="JGD2000 / Japan Plane Rectangular CS IX">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=139.8333333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2452" name="JGD2000 / Japan Plane Rectangular CS X">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=140.8333333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2453" name="JGD2000 / Japan Plane Rectangular CS XI">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=44"/>
+        <parameter value="lon_0=140.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2454" name="JGD2000 / Japan Plane Rectangular CS XII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=44"/>
+        <parameter value="lon_0=142.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2455" name="JGD2000 / Japan Plane Rectangular CS XIII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=44"/>
+        <parameter value="lon_0=144.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2456" name="JGD2000 / Japan Plane Rectangular CS XIV">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=142"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2457" name="JGD2000 / Japan Plane Rectangular CS XV">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=127.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2458" name="JGD2000 / Japan Plane Rectangular CS XVI">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=124"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2459" name="JGD2000 / Japan Plane Rectangular CS XVII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=131"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2460" name="JGD2000 / Japan Plane Rectangular CS XVIII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=20"/>
+        <parameter value="lon_0=136"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2461" name="JGD2000 / Japan Plane Rectangular CS XIX">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=154"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2462" name="Albanian 1987 / Gauss-Kruger zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2463" name="Pulkovo 1995 / Gauss-Kruger CM 21E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2464" name="Pulkovo 1995 / Gauss-Kruger CM 27E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2465" name="Pulkovo 1995 / Gauss-Kruger CM 33E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2466" name="Pulkovo 1995 / Gauss-Kruger CM 39E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2467" name="Pulkovo 1995 / Gauss-Kruger CM 45E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2468" name="Pulkovo 1995 / Gauss-Kruger CM 51E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2469" name="Pulkovo 1995 / Gauss-Kruger CM 57E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2470" name="Pulkovo 1995 / Gauss-Kruger CM 63E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2471" name="Pulkovo 1995 / Gauss-Kruger CM 69E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2472" name="Pulkovo 1995 / Gauss-Kruger CM 75E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2473" name="Pulkovo 1995 / Gauss-Kruger CM 81E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2474" name="Pulkovo 1995 / Gauss-Kruger CM 87E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2475" name="Pulkovo 1995 / Gauss-Kruger CM 93E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2476" name="Pulkovo 1995 / Gauss-Kruger CM 99E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2477" name="Pulkovo 1995 / Gauss-Kruger CM 105E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2478" name="Pulkovo 1995 / Gauss-Kruger CM 111E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2479" name="Pulkovo 1995 / Gauss-Kruger CM 117E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2480" name="Pulkovo 1995 / Gauss-Kruger CM 123E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2481" name="Pulkovo 1995 / Gauss-Kruger CM 129E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2482" name="Pulkovo 1995 / Gauss-Kruger CM 135E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2483" name="Pulkovo 1995 / Gauss-Kruger CM 141E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=141"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2484" name="Pulkovo 1995 / Gauss-Kruger CM 147E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=147"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2485" name="Pulkovo 1995 / Gauss-Kruger CM 153E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=153"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2486" name="Pulkovo 1995 / Gauss-Kruger CM 159E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=159"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2487" name="Pulkovo 1995 / Gauss-Kruger CM 165E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=165"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2488" name="Pulkovo 1995 / Gauss-Kruger CM 171E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2489" name="Pulkovo 1995 / Gauss-Kruger CM 177E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2490" name="Pulkovo 1995 / Gauss-Kruger CM 177W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2491" name="Pulkovo 1995 / Gauss-Kruger CM 171W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2492" name="Pulkovo 1942 / Gauss-Kruger CM 9E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=9"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2493" name="Pulkovo 1942 / Gauss-Kruger CM 15E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2494" name="Pulkovo 1942 / Gauss-Kruger CM 21E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2495" name="Pulkovo 1942 / Gauss-Kruger CM 27E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2496" name="Pulkovo 1942 / Gauss-Kruger CM 33E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2497" name="Pulkovo 1942 / Gauss-Kruger CM 39E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2498" name="Pulkovo 1942 / Gauss-Kruger CM 45E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2499" name="Pulkovo 1942 / Gauss-Kruger CM 51E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2500" name="Pulkovo 1942 / Gauss-Kruger CM 57E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2501" name="Pulkovo 1942 / Gauss-Kruger CM 63E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2502" name="Pulkovo 1942 / Gauss-Kruger CM 69E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2503" name="Pulkovo 1942 / Gauss-Kruger CM 75E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2504" name="Pulkovo 1942 / Gauss-Kruger CM 81E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2505" name="Pulkovo 1942 / Gauss-Kruger CM 87E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2506" name="Pulkovo 1942 / Gauss-Kruger CM 93E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2507" name="Pulkovo 1942 / Gauss-Kruger CM 99E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2508" name="Pulkovo 1942 / Gauss-Kruger CM 105E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2509" name="Pulkovo 1942 / Gauss-Kruger CM 111E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2510" name="Pulkovo 1942 / Gauss-Kruger CM 117E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2511" name="Pulkovo 1942 / Gauss-Kruger CM 123E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2512" name="Pulkovo 1942 / Gauss-Kruger CM 129E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2513" name="Pulkovo 1942 / Gauss-Kruger CM 135E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2514" name="Pulkovo 1942 / Gauss-Kruger CM 141E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=141"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2515" name="Pulkovo 1942 / Gauss-Kruger CM 147E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=147"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2516" name="Pulkovo 1942 / Gauss-Kruger CM 153E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=153"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2517" name="Pulkovo 1942 / Gauss-Kruger CM 159E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=159"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2518" name="Pulkovo 1942 / Gauss-Kruger CM 165E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=165"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2519" name="Pulkovo 1942 / Gauss-Kruger CM 171E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2520" name="Pulkovo 1942 / Gauss-Kruger CM 177E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2521" name="Pulkovo 1942 / Gauss-Kruger CM 177W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2522" name="Pulkovo 1942 / Gauss-Kruger CM 171W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2523" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=7500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2524" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=8500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2525" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=9500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2526" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=30"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=10500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2527" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 11">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=11500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2528" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 12">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=36"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=12500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2529" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 13">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=13500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2530" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 14">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=42"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=14500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2531" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 15">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=15500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2532" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 16">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=48"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=16500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2533" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 17">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=17500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2534" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 18">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=54"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=18500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2535" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 19">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=19500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2536" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 20">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=60"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=20500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2537" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 21">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=21500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2538" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 22">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=66"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=22500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2539" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 23">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=23500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2540" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 24">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=72"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=24500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2541" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 25">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=25500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2542" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 26">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=78"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=26500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2543" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 27">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=27500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2544" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 28">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=84"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=28500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2545" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 29">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=29500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2546" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 30">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=30500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2547" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 31">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=31500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2548" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 32">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=96"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=32500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2549" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 33">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=33500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2550" name="Samboja / UTM zone 50S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="south"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=-404.78,685.68,45.47,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2551" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 34">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=102"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=34500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2552" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 35">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=35500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2553" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 36">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=108"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=36500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2554" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 37">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=37500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2555" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 38">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=114"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=38500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2556" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 39">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=39500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2557" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 40">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=120"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=40500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2558" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 41">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=41500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2559" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 42">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=126"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=42500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2560" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 43">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=43500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2561" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 44">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=132"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=44500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2562" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 45">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=45500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2563" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 46">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=138"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=46500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2564" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 47">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=141"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=47500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2565" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 48">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=144"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=48500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2566" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 49">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=147"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=49500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2567" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 50">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=150"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=50500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2568" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 51">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=153"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=51500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2569" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 52">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=156"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=52500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2570" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 53">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=159"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=53500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2571" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 54">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=162"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=54500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2572" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 55">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=165"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=55500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2573" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 56">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=168"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=56500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2574" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 57">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=57500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2575" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 58">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=174"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=58500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2576" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 59">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=59500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2577" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 60">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=180"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=60000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2578" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 61">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=61500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2579" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 62">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-174"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=62500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2580" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 63">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=63500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2581" name="Pulkovo 1942 / 3-degree Gauss-Kruger zone 64">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-168"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=64500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2582" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 21E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2583" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 24E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2584" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 27E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2585" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 30E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=30"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2586" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 33E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2587" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 36E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=36"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2588" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 39E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2589" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 42E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=42"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2590" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 45E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2591" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 48E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=48"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2592" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 51E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2593" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 54E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=54"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2594" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 57E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2595" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 60E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=60"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2596" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 63E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2597" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 66E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=66"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2598" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 69E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2599" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 72E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=72"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2600" name="Lietuvos Koordinoei Sistema 1994">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=0.999800"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2601" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 75E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2602" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 78E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=78"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2603" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 81E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2604" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 84E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=84"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2605" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 87E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2606" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 90E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2607" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 93E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2608" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 96E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=96"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2609" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 99E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2610" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 102E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=102"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2611" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 105E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2612" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 108E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=108"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2613" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 111E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2614" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 114E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=114"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2615" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 117E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2616" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 120E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=120"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2617" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 123E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2618" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 126E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=126"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2619" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 129E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2620" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 132E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=132"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2621" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 135E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2622" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 138E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=138"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2623" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 141E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=141"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2624" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 144E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=144"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2625" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 147E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=147"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2626" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 150E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=150"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2627" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 153E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=153"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2628" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 156E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=156"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2629" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 159E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=159"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2630" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 162E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=162"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2631" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 165E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=165"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2632" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 168E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=168"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2633" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 171E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2634" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 174E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=174"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2635" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 177E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2636" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 180E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=180"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2637" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 177W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2638" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 174W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-174"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2639" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 171W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2640" name="Pulkovo 1942 / 3-degree Gauss-Kruger CM 168W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-168"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2641" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=7500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2642" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=8500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2643" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=9500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2644" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=30"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=10500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2645" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 11">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=11500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2646" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 12">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=36"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=12500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2647" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 13">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=13500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2648" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 14">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=42"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=14500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2649" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 15">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=15500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2650" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 16">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=48"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=16500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2651" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 17">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=17500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2652" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 18">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=54"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=18500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2653" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 19">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=19500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2654" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 20">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=60"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=20500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2655" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 21">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=21500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2656" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 22">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=66"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=22500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2657" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 23">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=23500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2658" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 24">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=72"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=24500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2659" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 25">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=25500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2660" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 26">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=78"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=26500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2661" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 27">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=27500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2662" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 28">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=84"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=28500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2663" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 29">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=29500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2664" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 30">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=30500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2665" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 31">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=31500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2666" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 32">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=96"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=32500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2667" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 33">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=33500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2668" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 34">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=102"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=34500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2669" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 35">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=35500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2670" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 36">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=108"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=36500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2671" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 37">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=37500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2672" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 38">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=114"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=38500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2673" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 39">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=39500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2674" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 40">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=120"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=40500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2675" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 41">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=41500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2676" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 42">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=126"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=42500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2677" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 43">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=43500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2678" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 44">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=132"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=44500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2679" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 45">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=45500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2680" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 46">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=138"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=46500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2681" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 47">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=141"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=47500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2682" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 48">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=144"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=48500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2683" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 49">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=147"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=49500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2684" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 50">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=150"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=50500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2685" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 51">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=153"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=51500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2686" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 52">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=156"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=52500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2687" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 53">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=159"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=53500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2688" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 54">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=162"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=54500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2689" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 55">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=165"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=55500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2690" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 56">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=168"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=56500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2691" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 57">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=57500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2692" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 58">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=174"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=58500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2693" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 59">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=59500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2694" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 60">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=180"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=60000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2695" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 61">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=61500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2696" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 62">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-174"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=62500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2697" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 63">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=63500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2698" name="Pulkovo 1995 / 3-degree Gauss-Kruger zone 64">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-168"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=64500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2699" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 21E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2700" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 24E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2701" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 27E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2702" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 30E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=30"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2703" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 33E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2704" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 36E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=36"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2705" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 39E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2706" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 42E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=42"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2707" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 45E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2708" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 48E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=48"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2709" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 51E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2710" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 54E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=54"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2711" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 57E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2712" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 60E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=60"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2713" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 63E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2714" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 66E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=66"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2715" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 69E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2716" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 72E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=72"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2717" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 75E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2718" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 78E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=78"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2719" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 81E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2720" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 84E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=84"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2721" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 87E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2722" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 90E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2723" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 93E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2724" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 96E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=96"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2725" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 99E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2726" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 102E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=102"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2727" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 105E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2728" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 108E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=108"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2729" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 111E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2730" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 114E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=114"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2731" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 117E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2732" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 120E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=120"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2733" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 123E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2734" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 126E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=126"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2735" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 129E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2736" name="Tete / UTM zone 36S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="south"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2737" name="Tete / UTM zone 37S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="south"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2738" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 132E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=132"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2739" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 135E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2740" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 138E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=138"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2741" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 141E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=141"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2742" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 144E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=144"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2743" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 147E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=147"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2744" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 150E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=150"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2745" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 153E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=153"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2746" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 156E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=156"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2747" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 159E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=159"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2748" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 162E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=162"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2749" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 165E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=165"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2750" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 168E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=168"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2751" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 171E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2752" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 174E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=174"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2753" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 177E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2754" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 180E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=180"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2755" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 177W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2756" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 174W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-174"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2757" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 171W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2758" name="Pulkovo 1995 / 3-degree Gauss-Kruger CM 168W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-168"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2759" name="NAD83(HARN) / Alabama East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30.5"/>
+        <parameter value="lon_0=-85.83333333333333"/>
+        <parameter value="k=0.999960"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2760" name="NAD83(HARN) / Alabama West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-87.5"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2761" name="NAD83(HARN) / Arizona East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-110.1666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2762" name="NAD83(HARN) / Arizona Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-111.9166666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2763" name="NAD83(HARN) / Arizona West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-113.75"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2764" name="NAD83(HARN) / Arkansas North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.23333333333333"/>
+        <parameter value="lat_2=34.93333333333333"/>
+        <parameter value="lat_0=34.33333333333334"/>
+        <parameter value="lon_0=-92"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2765" name="NAD83(HARN) / Arkansas South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=34.76666666666667"/>
+        <parameter value="lat_2=33.3"/>
+        <parameter value="lat_0=32.66666666666666"/>
+        <parameter value="lon_0=-92"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=400000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2766" name="NAD83(HARN) / California zone 1">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.66666666666666"/>
+        <parameter value="lat_2=40"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-122"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2767" name="NAD83(HARN) / California zone 2">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.83333333333334"/>
+        <parameter value="lat_2=38.33333333333334"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-122"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2768" name="NAD83(HARN) / California zone 3">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.43333333333333"/>
+        <parameter value="lat_2=37.06666666666667"/>
+        <parameter value="lat_0=36.5"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2769" name="NAD83(HARN) / California zone 4">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.25"/>
+        <parameter value="lat_2=36"/>
+        <parameter value="lat_0=35.33333333333334"/>
+        <parameter value="lon_0=-119"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2770" name="NAD83(HARN) / California zone 5">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.46666666666667"/>
+        <parameter value="lat_2=34.03333333333333"/>
+        <parameter value="lat_0=33.5"/>
+        <parameter value="lon_0=-118"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2771" name="NAD83(HARN) / California zone 6">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.88333333333333"/>
+        <parameter value="lat_2=32.78333333333333"/>
+        <parameter value="lat_0=32.16666666666666"/>
+        <parameter value="lon_0=-116.25"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2772" name="NAD83(HARN) / Colorado North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.78333333333333"/>
+        <parameter value="lat_2=39.71666666666667"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8289"/>
+        <parameter value="y_0=304800.6096"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2773" name="NAD83(HARN) / Colorado Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.75"/>
+        <parameter value="lat_2=38.45"/>
+        <parameter value="lat_0=37.83333333333334"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8289"/>
+        <parameter value="y_0=304800.6096"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2774" name="NAD83(HARN) / Colorado South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.43333333333333"/>
+        <parameter value="lat_2=37.23333333333333"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8289"/>
+        <parameter value="y_0=304800.6096"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2775" name="NAD83(HARN) / Connecticut">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.86666666666667"/>
+        <parameter value="lat_2=41.2"/>
+        <parameter value="lat_0=40.83333333333334"/>
+        <parameter value="lon_0=-72.75"/>
+        <parameter value="x_0=304800.6096"/>
+        <parameter value="y_0=152400.3048"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2776" name="NAD83(HARN) / Delaware">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=-75.41666666666667"/>
+        <parameter value="k=0.999995"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2777" name="NAD83(HARN) / Florida East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.33333333333333"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2778" name="NAD83(HARN) / Florida West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.33333333333333"/>
+        <parameter value="lon_0=-82"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2779" name="NAD83(HARN) / Florida North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.75"/>
+        <parameter value="lat_2=29.58333333333333"/>
+        <parameter value="lat_0=29"/>
+        <parameter value="lon_0=-84.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2780" name="NAD83(HARN) / Georgia East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-82.16666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2781" name="NAD83(HARN) / Georgia West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-84.16666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2782" name="NAD83(HARN) / Hawaii zone 1">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=18.83333333333333"/>
+        <parameter value="lon_0=-155.5"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2783" name="NAD83(HARN) / Hawaii zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=20.33333333333333"/>
+        <parameter value="lon_0=-156.6666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2784" name="NAD83(HARN) / Hawaii zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=21.16666666666667"/>
+        <parameter value="lon_0=-158"/>
+        <parameter value="k=0.999990"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2785" name="NAD83(HARN) / Hawaii zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=21.83333333333333"/>
+        <parameter value="lon_0=-159.5"/>
+        <parameter value="k=0.999990"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2786" name="NAD83(HARN) / Hawaii zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=21.66666666666667"/>
+        <parameter value="lon_0=-160.1666666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2787" name="NAD83(HARN) / Idaho East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-112.1666666666667"/>
+        <parameter value="k=0.999947"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2788" name="NAD83(HARN) / Idaho Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-114"/>
+        <parameter value="k=0.999947"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2789" name="NAD83(HARN) / Idaho West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-115.75"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2790" name="NAD83(HARN) / Illinois East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-88.33333333333333"/>
+        <parameter value="k=0.999975"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2791" name="NAD83(HARN) / Illinois West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-90.16666666666667"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2792" name="NAD83(HARN) / Indiana East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-85.66666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=100000"/>
+        <parameter value="y_0=250000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2793" name="NAD83(HARN) / Indiana West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-87.08333333333333"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=900000"/>
+        <parameter value="y_0=250000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2794" name="NAD83(HARN) / Iowa North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=43.26666666666667"/>
+        <parameter value="lat_2=42.06666666666667"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-93.5"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2795" name="NAD83(HARN) / Iowa South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.78333333333333"/>
+        <parameter value="lat_2=40.61666666666667"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-93.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2796" name="NAD83(HARN) / Kansas North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.78333333333333"/>
+        <parameter value="lat_2=38.71666666666667"/>
+        <parameter value="lat_0=38.33333333333334"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2797" name="NAD83(HARN) / Kansas South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.56666666666667"/>
+        <parameter value="lat_2=37.26666666666667"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=400000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2798" name="NAD83(HARN) / Kentucky North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.96666666666667"/>
+        <parameter value="lat_2=38.96666666666667"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-84.25"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2799" name="NAD83(HARN) / Kentucky South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.93333333333333"/>
+        <parameter value="lat_2=36.73333333333333"/>
+        <parameter value="lat_0=36.33333333333334"/>
+        <parameter value="lon_0=-85.75"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2800" name="NAD83(HARN) / Louisiana North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=32.66666666666666"/>
+        <parameter value="lat_2=31.16666666666667"/>
+        <parameter value="lat_0=30.5"/>
+        <parameter value="lon_0=-92.5"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2801" name="NAD83(HARN) / Louisiana South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.7"/>
+        <parameter value="lat_2=29.3"/>
+        <parameter value="lat_0=28.5"/>
+        <parameter value="lon_0=-91.33333333333333"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2802" name="NAD83(HARN) / Maine East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=43.66666666666666"/>
+        <parameter value="lon_0=-68.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2803" name="NAD83(HARN) / Maine West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=42.83333333333334"/>
+        <parameter value="lon_0=-70.16666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=900000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2804" name="NAD83(HARN) / Maryland">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.45"/>
+        <parameter value="lat_2=38.3"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-77"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2805" name="NAD83(HARN) / Massachusetts Mainland">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.68333333333333"/>
+        <parameter value="lat_2=41.71666666666667"/>
+        <parameter value="lat_0=41"/>
+        <parameter value="lon_0=-71.5"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=750000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2806" name="NAD83(HARN) / Massachusetts Island">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.48333333333333"/>
+        <parameter value="lat_2=41.28333333333333"/>
+        <parameter value="lat_0=41"/>
+        <parameter value="lon_0=-70.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2807" name="NAD83(HARN) / Michigan North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.08333333333334"/>
+        <parameter value="lat_2=45.48333333333333"/>
+        <parameter value="lat_0=44.78333333333333"/>
+        <parameter value="lon_0=-87"/>
+        <parameter value="x_0=8000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2808" name="NAD83(HARN) / Michigan Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.7"/>
+        <parameter value="lat_2=44.18333333333333"/>
+        <parameter value="lat_0=43.31666666666667"/>
+        <parameter value="lon_0=-84.36666666666666"/>
+        <parameter value="x_0=6000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2809" name="NAD83(HARN) / Michigan South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=43.66666666666666"/>
+        <parameter value="lat_2=42.1"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-84.36666666666666"/>
+        <parameter value="x_0=4000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2810" name="NAD83(HARN) / Minnesota North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.63333333333333"/>
+        <parameter value="lat_2=47.03333333333333"/>
+        <parameter value="lat_0=46.5"/>
+        <parameter value="lon_0=-93.09999999999999"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2811" name="NAD83(HARN) / Minnesota Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.05"/>
+        <parameter value="lat_2=45.61666666666667"/>
+        <parameter value="lat_0=45"/>
+        <parameter value="lon_0=-94.25"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2812" name="NAD83(HARN) / Minnesota South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.21666666666667"/>
+        <parameter value="lat_2=43.78333333333333"/>
+        <parameter value="lat_0=43"/>
+        <parameter value="lon_0=-94"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2813" name="NAD83(HARN) / Mississippi East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=29.5"/>
+        <parameter value="lon_0=-88.83333333333333"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2814" name="NAD83(HARN) / Mississippi West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=29.5"/>
+        <parameter value="lon_0=-90.33333333333333"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2815" name="NAD83(HARN) / Missouri East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=35.83333333333334"/>
+        <parameter value="lon_0=-90.5"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=250000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2816" name="NAD83(HARN) / Missouri Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=35.83333333333334"/>
+        <parameter value="lon_0=-92.5"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2817" name="NAD83(HARN) / Missouri West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36.16666666666666"/>
+        <parameter value="lon_0=-94.5"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=850000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2818" name="NAD83(HARN) / Montana">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49"/>
+        <parameter value="lat_2=45"/>
+        <parameter value="lat_0=44.25"/>
+        <parameter value="lon_0=-109.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2819" name="NAD83(HARN) / Nebraska">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=43"/>
+        <parameter value="lat_2=40"/>
+        <parameter value="lat_0=39.83333333333334"/>
+        <parameter value="lon_0=-100"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2820" name="NAD83(HARN) / Nevada East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=34.75"/>
+        <parameter value="lon_0=-115.5833333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=8000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2821" name="NAD83(HARN) / Nevada Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=34.75"/>
+        <parameter value="lon_0=-116.6666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=6000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2822" name="NAD83(HARN) / Nevada West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=34.75"/>
+        <parameter value="lon_0=-118.5833333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=4000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2823" name="NAD83(HARN) / New Hampshire">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=42.5"/>
+        <parameter value="lon_0=-71.66666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2824" name="NAD83(HARN) / New Jersey">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38.83333333333334"/>
+        <parameter value="lon_0=-74.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=150000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2825" name="NAD83(HARN) / New Mexico East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-104.3333333333333"/>
+        <parameter value="k=0.999909"/>
+        <parameter value="x_0=165000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2826" name="NAD83(HARN) / New Mexico Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-106.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2827" name="NAD83(HARN) / New Mexico West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-107.8333333333333"/>
+        <parameter value="k=0.999917"/>
+        <parameter value="x_0=830000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2828" name="NAD83(HARN) / New York East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38.83333333333334"/>
+        <parameter value="lon_0=-74.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=150000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2829" name="NAD83(HARN) / New York Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-76.58333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=250000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2830" name="NAD83(HARN) / New York West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-78.58333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=350000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2831" name="NAD83(HARN) / New York Long Island">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.03333333333333"/>
+        <parameter value="lat_2=40.66666666666666"/>
+        <parameter value="lat_0=40.16666666666666"/>
+        <parameter value="lon_0=-74"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2832" name="NAD83(HARN) / North Dakota North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.73333333333333"/>
+        <parameter value="lat_2=47.43333333333333"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-100.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2833" name="NAD83(HARN) / North Dakota South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.48333333333333"/>
+        <parameter value="lat_2=46.18333333333333"/>
+        <parameter value="lat_0=45.66666666666666"/>
+        <parameter value="lon_0=-100.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2834" name="NAD83(HARN) / Ohio North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.7"/>
+        <parameter value="lat_2=40.43333333333333"/>
+        <parameter value="lat_0=39.66666666666666"/>
+        <parameter value="lon_0=-82.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2835" name="NAD83(HARN) / Ohio South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.03333333333333"/>
+        <parameter value="lat_2=38.73333333333333"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=-82.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2836" name="NAD83(HARN) / Oklahoma North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.76666666666667"/>
+        <parameter value="lat_2=35.56666666666667"/>
+        <parameter value="lat_0=35"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2837" name="NAD83(HARN) / Oklahoma South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.23333333333333"/>
+        <parameter value="lat_2=33.93333333333333"/>
+        <parameter value="lat_0=33.33333333333334"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2838" name="NAD83(HARN) / Oregon North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46"/>
+        <parameter value="lat_2=44.33333333333334"/>
+        <parameter value="lat_0=43.66666666666666"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2839" name="NAD83(HARN) / Oregon South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44"/>
+        <parameter value="lat_2=42.33333333333334"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2840" name="NAD83(HARN) / Rhode Island">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.08333333333334"/>
+        <parameter value="lon_0=-71.5"/>
+        <parameter value="k=0.999994"/>
+        <parameter value="x_0=100000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2841" name="NAD83(HARN) / South Dakota North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.68333333333333"/>
+        <parameter value="lat_2=44.41666666666666"/>
+        <parameter value="lat_0=43.83333333333334"/>
+        <parameter value="lon_0=-100"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2842" name="NAD83(HARN) / South Dakota South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.4"/>
+        <parameter value="lat_2=42.83333333333334"/>
+        <parameter value="lat_0=42.33333333333334"/>
+        <parameter value="lon_0=-100.3333333333333"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2843" name="NAD83(HARN) / Tennessee">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.41666666666666"/>
+        <parameter value="lat_2=35.25"/>
+        <parameter value="lat_0=34.33333333333334"/>
+        <parameter value="lon_0=-86"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2844" name="NAD83(HARN) / Texas North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.18333333333333"/>
+        <parameter value="lat_2=34.65"/>
+        <parameter value="lat_0=34"/>
+        <parameter value="lon_0=-101.5"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2845" name="NAD83(HARN) / Texas North Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.96666666666667"/>
+        <parameter value="lat_2=32.13333333333333"/>
+        <parameter value="lat_0=31.66666666666667"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=2000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2846" name="NAD83(HARN) / Texas Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=31.88333333333333"/>
+        <parameter value="lat_2=30.11666666666667"/>
+        <parameter value="lat_0=29.66666666666667"/>
+        <parameter value="lon_0=-100.3333333333333"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=3000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2847" name="NAD83(HARN) / Texas South Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.28333333333333"/>
+        <parameter value="lat_2=28.38333333333333"/>
+        <parameter value="lat_0=27.83333333333333"/>
+        <parameter value="lon_0=-99"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=4000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2848" name="NAD83(HARN) / Texas South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=27.83333333333333"/>
+        <parameter value="lat_2=26.16666666666667"/>
+        <parameter value="lat_0=25.66666666666667"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=5000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2849" name="NAD83(HARN) / Utah North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.78333333333333"/>
+        <parameter value="lat_2=40.71666666666667"/>
+        <parameter value="lat_0=40.33333333333334"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2850" name="NAD83(HARN) / Utah Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.65"/>
+        <parameter value="lat_2=39.01666666666667"/>
+        <parameter value="lat_0=38.33333333333334"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=2000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2851" name="NAD83(HARN) / Utah South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.35"/>
+        <parameter value="lat_2=37.21666666666667"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=3000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2852" name="NAD83(HARN) / Vermont">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=42.5"/>
+        <parameter value="lon_0=-72.5"/>
+        <parameter value="k=0.999964"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2853" name="NAD83(HARN) / Virginia North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.2"/>
+        <parameter value="lat_2=38.03333333333333"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-78.5"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=2000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2854" name="NAD83(HARN) / Virginia South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.96666666666667"/>
+        <parameter value="lat_2=36.76666666666667"/>
+        <parameter value="lat_0=36.33333333333334"/>
+        <parameter value="lon_0=-78.5"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2855" name="NAD83(HARN) / Washington North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.73333333333333"/>
+        <parameter value="lat_2=47.5"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-120.8333333333333"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2856" name="NAD83(HARN) / Washington South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.33333333333334"/>
+        <parameter value="lat_2=45.83333333333334"/>
+        <parameter value="lat_0=45.33333333333334"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2857" name="NAD83(HARN) / West Virginia North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.25"/>
+        <parameter value="lat_2=39"/>
+        <parameter value="lat_0=38.5"/>
+        <parameter value="lon_0=-79.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2858" name="NAD83(HARN) / West Virginia South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.88333333333333"/>
+        <parameter value="lat_2=37.48333333333333"/>
+        <parameter value="lat_0=37"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2859" name="NAD83(HARN) / Wisconsin North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.76666666666667"/>
+        <parameter value="lat_2=45.56666666666667"/>
+        <parameter value="lat_0=45.16666666666666"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2860" name="NAD83(HARN) / Wisconsin Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.5"/>
+        <parameter value="lat_2=44.25"/>
+        <parameter value="lat_0=43.83333333333334"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2861" name="NAD83(HARN) / Wisconsin South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.06666666666667"/>
+        <parameter value="lat_2=42.73333333333333"/>
+        <parameter value="lat_0=42"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2862" name="NAD83(HARN) / Wyoming East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.5"/>
+        <parameter value="lon_0=-105.1666666666667"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2863" name="NAD83(HARN) / Wyoming East Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.5"/>
+        <parameter value="lon_0=-107.3333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2864" name="NAD83(HARN) / Wyoming West Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.5"/>
+        <parameter value="lon_0=-108.75"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2865" name="NAD83(HARN) / Wyoming West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.5"/>
+        <parameter value="lon_0=-110.0833333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2866" name="NAD83(HARN) / Puerto Rico &amp; Virgin Is.">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=18.43333333333333"/>
+        <parameter value="lat_2=18.03333333333333"/>
+        <parameter value="lat_0=17.83333333333333"/>
+        <parameter value="lon_0=-66.43333333333334"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=200000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2867" name="NAD83(HARN) / Arizona East (ft)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-110.1666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2868" name="NAD83(HARN) / Arizona Central (ft)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-111.9166666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2869" name="NAD83(HARN) / Arizona West (ft)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-113.75"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2870" name="NAD83(HARN) / California zone 1 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.66666666666666"/>
+        <parameter value="lat_2=40"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-122"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2871" name="NAD83(HARN) / California zone 2 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.83333333333334"/>
+        <parameter value="lat_2=38.33333333333334"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-122"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2872" name="NAD83(HARN) / California zone 3 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.43333333333333"/>
+        <parameter value="lat_2=37.06666666666667"/>
+        <parameter value="lat_0=36.5"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2873" name="NAD83(HARN) / California zone 4 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.25"/>
+        <parameter value="lat_2=36"/>
+        <parameter value="lat_0=35.33333333333334"/>
+        <parameter value="lon_0=-119"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2874" name="NAD83(HARN) / California zone 5 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.46666666666667"/>
+        <parameter value="lat_2=34.03333333333333"/>
+        <parameter value="lat_0=33.5"/>
+        <parameter value="lon_0=-118"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2875" name="NAD83(HARN) / California zone 6 (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.88333333333333"/>
+        <parameter value="lat_2=32.78333333333333"/>
+        <parameter value="lat_0=32.16666666666666"/>
+        <parameter value="lon_0=-116.25"/>
+        <parameter value="x_0=2000000.0001016"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2876" name="NAD83(HARN) / Colorado North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.78333333333333"/>
+        <parameter value="lat_2=39.71666666666667"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8288036576"/>
+        <parameter value="y_0=304800.6096012192"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2877" name="NAD83(HARN) / Colorado Central (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.75"/>
+        <parameter value="lat_2=38.45"/>
+        <parameter value="lat_0=37.83333333333334"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8288036576"/>
+        <parameter value="y_0=304800.6096012192"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2878" name="NAD83(HARN) / Colorado South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.43333333333333"/>
+        <parameter value="lat_2=37.23333333333333"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8288036576"/>
+        <parameter value="y_0=304800.6096012192"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2879" name="NAD83(HARN) / Connecticut (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.86666666666667"/>
+        <parameter value="lat_2=41.2"/>
+        <parameter value="lat_0=40.83333333333334"/>
+        <parameter value="lon_0=-72.75"/>
+        <parameter value="x_0=304800.6096012192"/>
+        <parameter value="y_0=152400.3048006096"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2880" name="NAD83(HARN) / Delaware (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=-75.41666666666667"/>
+        <parameter value="k=0.999995"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2881" name="NAD83(HARN) / Florida East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.33333333333333"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2882" name="NAD83(HARN) / Florida West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.33333333333333"/>
+        <parameter value="lon_0=-82"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2883" name="NAD83(HARN) / Florida North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.75"/>
+        <parameter value="lat_2=29.58333333333333"/>
+        <parameter value="lat_0=29"/>
+        <parameter value="lon_0=-84.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2884" name="NAD83(HARN) / Georgia East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-82.16666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2885" name="NAD83(HARN) / Georgia West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-84.16666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=699999.9998983998"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2886" name="NAD83(HARN) / Idaho East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-112.1666666666667"/>
+        <parameter value="k=0.999947"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2887" name="NAD83(HARN) / Idaho Central (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-114"/>
+        <parameter value="k=0.999947"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2888" name="NAD83(HARN) / Idaho West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-115.75"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=800000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2889" name="NAD83(HARN) / Indiana East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-85.66666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=99999.99989839978"/>
+        <parameter value="y_0=249364.9987299975"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2890" name="NAD83(HARN) / Indiana West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-87.08333333333333"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=900000"/>
+        <parameter value="y_0=249364.9987299975"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2891" name="NAD83(HARN) / Kentucky North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.96666666666667"/>
+        <parameter value="lat_2=38.96666666666667"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-84.25"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2892" name="NAD83(HARN) / Kentucky South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.93333333333333"/>
+        <parameter value="lat_2=36.73333333333333"/>
+        <parameter value="lat_0=36.33333333333334"/>
+        <parameter value="lon_0=-85.75"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=500000.0001016001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2893" name="NAD83(HARN) / Maryland (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.45"/>
+        <parameter value="lat_2=38.3"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-77"/>
+        <parameter value="x_0=399999.9998983998"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2894" name="NAD83(HARN) / Massachusetts Mainland (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.68333333333333"/>
+        <parameter value="lat_2=41.71666666666667"/>
+        <parameter value="lat_0=41"/>
+        <parameter value="lon_0=-71.5"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=750000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2895" name="NAD83(HARN) / Massachusetts Island (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.48333333333333"/>
+        <parameter value="lat_2=41.28333333333333"/>
+        <parameter value="lat_0=41"/>
+        <parameter value="lon_0=-70.5"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2896" name="NAD83(HARN) / Michigan North (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.08333333333334"/>
+        <parameter value="lat_2=45.48333333333333"/>
+        <parameter value="lat_0=44.78333333333333"/>
+        <parameter value="lon_0=-87"/>
+        <parameter value="x_0=7999999.999968001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2897" name="NAD83(HARN) / Michigan Central (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.7"/>
+        <parameter value="lat_2=44.18333333333333"/>
+        <parameter value="lat_0=43.31666666666667"/>
+        <parameter value="lon_0=-84.36666666666666"/>
+        <parameter value="x_0=5999999.999976001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2898" name="NAD83(HARN) / Michigan South (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=43.66666666666666"/>
+        <parameter value="lat_2=42.1"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-84.36666666666666"/>
+        <parameter value="x_0=3999999.999984"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2899" name="NAD83(HARN) / Mississippi East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=29.5"/>
+        <parameter value="lon_0=-88.83333333333333"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=300000.0000000001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2900" name="NAD83(HARN) / Mississippi West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=29.5"/>
+        <parameter value="lon_0=-90.33333333333333"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=699999.9998983998"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2901" name="NAD83(HARN) / Montana (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49"/>
+        <parameter value="lat_2=45"/>
+        <parameter value="lat_0=44.25"/>
+        <parameter value="lon_0=-109.5"/>
+        <parameter value="x_0=599999.9999976"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2902" name="NAD83(HARN) / New Mexico East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-104.3333333333333"/>
+        <parameter value="k=0.999909"/>
+        <parameter value="x_0=165000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2903" name="NAD83(HARN) / New Mexico Central (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-106.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2904" name="NAD83(HARN) / New Mexico West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-107.8333333333333"/>
+        <parameter value="k=0.999917"/>
+        <parameter value="x_0=830000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2905" name="NAD83(HARN) / New York East (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38.83333333333334"/>
+        <parameter value="lon_0=-74.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=150000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2906" name="NAD83(HARN) / New York Central (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-76.58333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=249999.9998983998"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2907" name="NAD83(HARN) / New York West (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-78.58333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=350000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2908" name="NAD83(HARN) / New York Long Island (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.03333333333333"/>
+        <parameter value="lat_2=40.66666666666666"/>
+        <parameter value="lat_0=40.16666666666666"/>
+        <parameter value="lon_0=-74"/>
+        <parameter value="x_0=300000.0000000001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2909" name="NAD83(HARN) / North Dakota North (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.73333333333333"/>
+        <parameter value="lat_2=47.43333333333333"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-100.5"/>
+        <parameter value="x_0=599999.9999976"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2910" name="NAD83(HARN) / North Dakota South (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.48333333333333"/>
+        <parameter value="lat_2=46.18333333333333"/>
+        <parameter value="lat_0=45.66666666666666"/>
+        <parameter value="lon_0=-100.5"/>
+        <parameter value="x_0=599999.9999976"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2911" name="NAD83(HARN) / Oklahoma North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.76666666666667"/>
+        <parameter value="lat_2=35.56666666666667"/>
+        <parameter value="lat_0=35"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2912" name="NAD83(HARN) / Oklahoma South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.23333333333333"/>
+        <parameter value="lat_2=33.93333333333333"/>
+        <parameter value="lat_0=33.33333333333334"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2913" name="NAD83(HARN) / Oregon North (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46"/>
+        <parameter value="lat_2=44.33333333333334"/>
+        <parameter value="lat_0=43.66666666666666"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=2500000.0001424"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2914" name="NAD83(HARN) / Oregon South (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44"/>
+        <parameter value="lat_2=42.33333333333334"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=1500000.0001464"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2915" name="NAD83(HARN) / Tennessee (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.41666666666666"/>
+        <parameter value="lat_2=35.25"/>
+        <parameter value="lat_0=34.33333333333334"/>
+        <parameter value="lon_0=-86"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2916" name="NAD83(HARN) / Texas North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.18333333333333"/>
+        <parameter value="lat_2=34.65"/>
+        <parameter value="lat_0=34"/>
+        <parameter value="lon_0=-101.5"/>
+        <parameter value="x_0=200000.0001016002"/>
+        <parameter value="y_0=999999.9998983998"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2917" name="NAD83(HARN) / Texas North Central (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.96666666666667"/>
+        <parameter value="lat_2=32.13333333333333"/>
+        <parameter value="lat_0=31.66666666666667"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=2000000.0001016"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2918" name="NAD83(HARN) / Texas Central (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=31.88333333333333"/>
+        <parameter value="lat_2=30.11666666666667"/>
+        <parameter value="lat_0=29.66666666666667"/>
+        <parameter value="lon_0=-100.3333333333333"/>
+        <parameter value="x_0=699999.9998983998"/>
+        <parameter value="y_0=3000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2919" name="NAD83(HARN) / Texas South Central (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.28333333333333"/>
+        <parameter value="lat_2=28.38333333333333"/>
+        <parameter value="lat_0=27.83333333333333"/>
+        <parameter value="lon_0=-99"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=3999999.9998984"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2920" name="NAD83(HARN) / Texas South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=27.83333333333333"/>
+        <parameter value="lat_2=26.16666666666667"/>
+        <parameter value="lat_0=25.66666666666667"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=300000.0000000001"/>
+        <parameter value="y_0=5000000.0001016"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2921" name="NAD83(HARN) / Utah North (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.78333333333333"/>
+        <parameter value="lat_2=40.71666666666667"/>
+        <parameter value="lat_0=40.33333333333334"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000.0001504"/>
+        <parameter value="y_0=999999.9999960001"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2922" name="NAD83(HARN) / Utah Central (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.65"/>
+        <parameter value="lat_2=39.01666666666667"/>
+        <parameter value="lat_0=38.33333333333334"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000.0001504"/>
+        <parameter value="y_0=1999999.999992"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2923" name="NAD83(HARN) / Utah South (ft)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.35"/>
+        <parameter value="lat_2=37.21666666666667"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000.0001504"/>
+        <parameter value="y_0=2999999.999988"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2924" name="NAD83(HARN) / Virginia North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.2"/>
+        <parameter value="lat_2=38.03333333333333"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-78.5"/>
+        <parameter value="x_0=3500000.0001016"/>
+        <parameter value="y_0=2000000.0001016"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2925" name="NAD83(HARN) / Virginia South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.96666666666667"/>
+        <parameter value="lat_2=36.76666666666667"/>
+        <parameter value="lat_0=36.33333333333334"/>
+        <parameter value="lon_0=-78.5"/>
+        <parameter value="x_0=3500000.0001016"/>
+        <parameter value="y_0=999999.9998983998"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2926" name="NAD83(HARN) / Washington North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.73333333333333"/>
+        <parameter value="lat_2=47.5"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-120.8333333333333"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2927" name="NAD83(HARN) / Washington South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.33333333333334"/>
+        <parameter value="lat_2=45.83333333333334"/>
+        <parameter value="lat_0=45.33333333333334"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=500000.0001016001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2928" name="NAD83(HARN) / Wisconsin North (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.76666666666667"/>
+        <parameter value="lat_2=45.56666666666667"/>
+        <parameter value="lat_0=45.16666666666666"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2929" name="NAD83(HARN) / Wisconsin Central (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.5"/>
+        <parameter value="lat_2=44.25"/>
+        <parameter value="lat_0=43.83333333333334"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2930" name="NAD83(HARN) / Wisconsin South (ftUS)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.06666666666667"/>
+        <parameter value="lat_2=42.73333333333333"/>
+        <parameter value="lat_0=42"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2931" name="Beduaram / TM 13 NE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=13"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000.0000000001"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2932" name="QND95 / Qatar National Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.45"/>
+        <parameter value="lon_0=51.21666666666667"/>
+        <parameter value="k=0.999990"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-119.425,-303.659,-11.0006,1.1643,0.174458,1.09626,3.65706"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2933" name="Segara / UTM zone 50S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="south"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=-404.78,685.68,45.47,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2934" name="Segara (Jakarta) / NEIEZ">
+        <parameter value="proj=merc"/>
+        <parameter value="lat_ts=0"/>
+        <parameter value="lon_0=216.8077194444444"/>
+        <parameter value="k=0.997000"/>
+        <parameter value="x_0=3900000"/>
+        <parameter value="y_0=900000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=jakarta"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2935" name="Pulkovo 1942 / CS63 zone A1">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0.1166666666666667"/>
+        <parameter value="lon_0=41.53333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=1300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2936" name="Pulkovo 1942 / CS63 zone A2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0.1166666666666667"/>
+        <parameter value="lon_0=44.53333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=2300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2937" name="Pulkovo 1942 / CS63 zone A3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0.1166666666666667"/>
+        <parameter value="lon_0=47.53333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=3300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2938" name="Pulkovo 1942 / CS63 zone A4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0.1166666666666667"/>
+        <parameter value="lon_0=50.53333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2939" name="Pulkovo 1942 / CS63 zone K2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0.1333333333333333"/>
+        <parameter value="lon_0=50.76666666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=2300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2940" name="Pulkovo 1942 / CS63 zone K3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0.1333333333333333"/>
+        <parameter value="lon_0=53.76666666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=3300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2941" name="Pulkovo 1942 / CS63 zone K4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0.1333333333333333"/>
+        <parameter value="lon_0=56.76666666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2942" name="Porto Santo / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2943" name="Selvagem Grande / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2944" name="NAD83(CSRS) / SCoPQ zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-55.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2945" name="NAD83(CSRS) / MTM zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-58.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2946" name="NAD83(CSRS) / MTM zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-61.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2947" name="NAD83(CSRS) / MTM zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-64.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2948" name="NAD83(CSRS) / MTM zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-67.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2949" name="NAD83(CSRS) / MTM zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-70.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2950" name="NAD83(CSRS) / MTM zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-73.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2951" name="NAD83(CSRS) / MTM zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-76.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2952" name="NAD83(CSRS) / MTM zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-79.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2953" name="NAD83(CSRS) / New Brunswick Stereo">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=46.5"/>
+        <parameter value="lon_0=-66.5"/>
+        <parameter value="k=0.999912"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=7500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2954" name="NAD83(CSRS) / Prince Edward Isl. Stereographic (NAD83)">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=47.25"/>
+        <parameter value="lon_0=-63"/>
+        <parameter value="k=0.999912"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2955" name="NAD83(CSRS) / UTM zone 11N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=11"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2956" name="NAD83(CSRS) / UTM zone 12N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=12"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2957" name="NAD83(CSRS) / UTM zone 13N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=13"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2958" name="NAD83(CSRS) / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2959" name="NAD83(CSRS) / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2960" name="NAD83(CSRS) / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2961" name="NAD83(CSRS) / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="2962" name="NAD83(CSRS) / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3036" name="Moznet / UTM zone 36S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="towgs84=0,0,0,-0,-0,-0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3037" name="Moznet / UTM zone 37S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="towgs84=0,0,0,-0,-0,-0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3148" name="Indian 1960 / UTM zone 48N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3149" name="Indian 1960 / UTM zone 49N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3176" name="Indian 1960 / TM 106 NE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=106"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3200" name="FD58 / Iraq zone">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=32.5"/>
+        <parameter value="lat_0=32.5"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k_0=0.9987864078000001"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=1166200"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3300" name="Estonian Coordinate System of 1992">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=59.33333333333334"/>
+        <parameter value="lat_2=58"/>
+        <parameter value="lat_0=57.51755393055556"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=6375000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0.055,-0.541,-0.185,0.0183,-0.0003,-0.007,-0.014"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3301" name="Estonian Coordinate System of 1997">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=59.33333333333334"/>
+        <parameter value="lat_2=58"/>
+        <parameter value="lat_0=57.51755393055556"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=6375000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3439" name="PSD93 / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3440" name="PSD93 / UTM zone 40N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3561" name="Old Hawaiian / Hawaii zone 1">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=18.83333333333333"/>
+        <parameter value="lon_0=-155.5"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3562" name="Old Hawaiian / Hawaii zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=20.33333333333333"/>
+        <parameter value="lon_0=-156.6666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3563" name="Old Hawaiian / Hawaii zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=21.16666666666667"/>
+        <parameter value="lon_0=-158"/>
+        <parameter value="k=0.999990"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3564" name="Old Hawaiian / Hawaii zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=21.83333333333333"/>
+        <parameter value="lon_0=-159.5"/>
+        <parameter value="k=0.999990"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3565" name="Old Hawaiian / Hawaii zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=21.66666666666667"/>
+        <parameter value="lon_0=-160.1666666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3920" name="Puerto Rico / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3991" name="Puerto Rico State Plane CS of 1927">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=18.43333333333333"/>
+        <parameter value="lat_2=18.03333333333333"/>
+        <parameter value="lat_0=17.83333333333333"/>
+        <parameter value="lon_0=-66.43333333333334"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="3992" name="Puerto Rico / St. Croix">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=18.43333333333333"/>
+        <parameter value="lat_2=18.03333333333333"/>
+        <parameter value="lat_0=17.83333333333333"/>
+        <parameter value="lon_0=-66.43333333333334"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=30480.06096012192"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4001" name="Unknown datum based upon the Airy 1830 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=airy"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4002" name="Unknown datum based upon the Airy Modified 1849 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377340.189"/>
+        <parameter value="b=6356034.447938534"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4003" name="Unknown datum based upon the Australian National Spheroid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4004" name="Unknown datum based upon the Bessel 1841 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4005" name="Unknown datum based upon the Bessel Modified ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4006" name="Unknown datum based upon the Bessel Namibia ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bess_nam"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4007" name="Unknown datum based upon the Clarke 1858 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378293.63683822"/>
+        <parameter value="b=6356617.979337744"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4008" name="Unknown datum based upon the Clarke 1866 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4009" name="Unknown datum based upon the Clarke 1866 Michigan ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378450.047548896"/>
+        <parameter value="b=6356826.621488444"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4010" name="Unknown datum based upon the Clarke 1880 (Benoit) ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378300.789"/>
+        <parameter value="b=6356566.435"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4011" name="Unknown datum based upon the Clarke 1880 (IGN) ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4012" name="Unknown datum based upon the Clarke 1880 (RGS) ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4013" name="Unknown datum based upon the Clarke 1880 (Arc) ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.145"/>
+        <parameter value="b=6356514.966398753"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4014" name="Unknown datum based upon the Clarke 1880 (SGA 1922) ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356514.996941779"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4015" name="Unknown datum based upon the Everest 1830 (1937 Adjustment) ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4016" name="Unknown datum based upon the Everest 1830 (1967 Definition) ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=evrstSS"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4018" name="Unknown datum based upon the Everest 1830 Modified ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377304.063"/>
+        <parameter value="b=6356103.038993155"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4019" name="Unknown datum based upon the GRS 1980 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4020" name="Unknown datum based upon the Helmert 1906 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4021" name="Unknown datum based upon the Indonesian National Spheroid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4022" name="Unknown datum based upon the International 1924 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4024" name="Unknown datum based upon the Krassowsky 1940 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4025" name="Unknown datum based upon the NWL 9D ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4027" name="Unknown datum based upon the Plessis 1817 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6376523"/>
+        <parameter value="b=6355862.933255573"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4028" name="Unknown datum based upon the Struve 1860 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378298.3"/>
+        <parameter value="b=6356657.142669562"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4029" name="Unknown datum based upon the War Office ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378300"/>
+        <parameter value="b=6356751.689189189"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4030" name="Unknown datum based upon the WGS 84 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4031" name="Unknown datum based upon the GEM 10C ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4032" name="Unknown datum based upon the OSU86F ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378136.2"/>
+        <parameter value="b=6356751.516927429"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4033" name="Unknown datum based upon the OSU91A ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378136.3"/>
+        <parameter value="b=6356751.616592146"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4034" name="Unknown datum based upon the Clarke 1880 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4035" name="Unknown datum based upon the Authalic Sphere">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6371000"/>
+        <parameter value="b=6371000"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4036" name="Unknown datum based upon the GRS 1967 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4041" name="Unknown datum based upon the Average Terrestrial System 1977 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378135"/>
+        <parameter value="b=6356750.304921594"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4042" name="Unknown datum based upon the Everest (1830 Definition) ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377299.36559538"/>
+        <parameter value="b=6356098.357204817"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4043" name="Unknown datum based upon the WGS 72 ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4044" name="Unknown datum based upon the Everest 1830 (1962 Definition) ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377301.243"/>
+        <parameter value="b=6356100.230165385"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4045" name="Unknown datum based upon the Everest 1830 (1975 Definition) ellipsoid">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4047" name="Unspecified based upon the GRS 1980 Authalic Sphere">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6370997"/>
+        <parameter value="b=6370997"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4120" name="Greek">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4121" name="GGRS87">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=-199.87,74.79,246.62,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4122" name="ATS77">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378135"/>
+        <parameter value="b=6356750.304921594"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4123" name="KKJ">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-90.7,-106.1,-119.2,4.09,0.218,-1.05,1.37"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4124" name="RT90">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4125" name="Samboja">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=-404.78,685.68,45.47,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4126" name="LKS94 (ETRS89)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4127" name="Tete">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4128" name="Madzansua">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4129" name="Observatario">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4130" name="Moznet">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="towgs84=0,0,0,-0,-0,-0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4131" name="Indian 1960">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4132" name="FD58">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4133" name="EST92">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0.055,-0.541,-0.185,0.0183,-0.0003,-0.007,-0.014"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4134" name="PDO Survey Datum 1993">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4135" name="Old Hawaiian">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4136" name="St. Lawrence Island">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4137" name="St. Paul Island">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4138" name="St. George Island">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4139" name="Puerto Rico">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4140" name="NAD83(CSRS98)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4141" name="Israel">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4142" name="Locodjo 1965">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-125,53,467,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4143" name="Abidjan 1987">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-124.76,53,466.79,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4144" name="Kalianpur 1937">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4145" name="Kalianpur 1962">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377301.243"/>
+        <parameter value="b=6356100.230165385"/>
+        <parameter value="towgs84=283,682,231,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4146" name="Kalianpur 1975">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4147" name="Hanoi 1972">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-17.51,-108.32,-62.39,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4148" name="Hartebeesthoek94">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4149" name="CH1903">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4150" name="CH1903+">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=674.374,15.056,405.346,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4151" name="CHTRF95">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4152" name="NAD83(HARN)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4153" name="Rassadiran">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-133.63,-157.5,-158.62,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4154" name="ED50(ED77)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4155" name="Dabola 1981">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-83,37,124,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4156" name="S-JTSK">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4157" name="Mount Dillon">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378293.63683822"/>
+        <parameter value="b=6356617.979337744"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4158" name="Naparima 1955">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4159" name="ELD79">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4160" name="Chos Malal 1914">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4161" name="Pampa del Castillo">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4162" name="Korean 1985">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4163" name="Yemen NGN96">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4164" name="South Yemen">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-76,-138,67,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4165" name="Bissau">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-173,253,27,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4166" name="Korean 1995">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4167" name="NZGD2000">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4168" name="Accra">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378300"/>
+        <parameter value="b=6356751.689189189"/>
+        <parameter value="towgs84=-199,32,322,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4169" name="American Samoa 1962">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="towgs84=-115,118,426,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4170" name="SIRGAS">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4171" name="RGF93">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4172" name="POSGAR">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4173" name="IRENET95">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4174" name="Sierra Leone 1924">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378300"/>
+        <parameter value="b=6356751.689189189"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4175" name="Sierra Leone 1968">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-88,4,101,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4176" name="Australian Antarctic">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4178" name="Pulkovo 1942(83)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=24,-123,-94,0.02,-0.25,-0.13,1.1"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4179" name="Pulkovo 1942(58)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4180" name="EST97">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4181" name="Luxembourg 1930">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-193,13.7,-39.3,-0.41,-2.933,2.688,0.43"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4182" name="Azores Occidental 1939">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4183" name="Azores Central 1948">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4184" name="Azores Oriental 1940">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4185" name="Madeira 1936">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4188" name="OSNI 1952">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=airy"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4189" name="REGVEN">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4190" name="POSGAR 98">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4191" name="Albanian 1987">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4192" name="Douala 1948">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4193" name="Manoca 1962">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-70.9,-151.8,-41.4,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4194" name="Qornoq 1927">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4195" name="Scoresbysund 1952">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=105,326,-102.5,0,0,0.814,-0.6"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4196" name="Ammassalik 1958">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-45,417,-3.5,0,0,0.814,-0.6"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4197" name="Garoua">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4198" name="Kousseri">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4199" name="Egypt 1930">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4200" name="Pulkovo 1995">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4201" name="Adindan">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4202" name="AGD66">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4203" name="AGD84">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4204" name="Ain el Abd">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4205" name="Afgooye">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-43,-163,45,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4206" name="Agadez">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4207" name="Lisbon">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4208" name="Aratu">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4209" name="Arc 1950">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.145"/>
+        <parameter value="b=6356514.966398753"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4210" name="Arc 1960">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4211" name="Batavia">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4212" name="Barbados 1938">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4213" name="Beduaram">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4214" name="Beijing 1954">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4215" name="Belge 1950">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4216" name="Bermuda 1957">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="towgs84=-73,213,296,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4218" name="Bogota 1975">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4219" name="Bukit Rimpah">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=-384,664,-48,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4220" name="Camacupa">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4221" name="Campo Inchauspe">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4222" name="Cape">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.145"/>
+        <parameter value="b=6356514.966398753"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4223" name="Carthage">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4224" name="Chua">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-134,229,-29,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4225" name="Corrego Alegre">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-206,172,-6,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4226" name="Cote d&apos;Ivoire">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4227" name="Deir ez Zor">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4228" name="Douala">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4229" name="Egypt 1907">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4230" name="ED50">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4231" name="ED87">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-82.981,-99.719,-110.709,-0.5076,0.1503,0.3898,-0.3143"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4232" name="Fahud">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4233" name="Gandajika 1970">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4234" name="Garoua">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4235" name="Guyane Francaise">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4236" name="Hu Tzu Shan">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-637,-549,-203,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4237" name="HD72">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4238" name="ID74">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4239" name="Indian 1954">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="towgs84=217,823,299,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4240" name="Indian 1975">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4241" name="Jamaica 1875">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4242" name="JAD69">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4243" name="Kalianpur 1880">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377299.36559538"/>
+        <parameter value="b=6356098.357204817"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4244" name="Kandawala">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="towgs84=-97,787,86,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4245" name="Kertau">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377304.063"/>
+        <parameter value="b=6356103.038993155"/>
+        <parameter value="towgs84=-11,851,5,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4246" name="KOC">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4247" name="La Canoa">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-273.5,110.6,-357.9,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4248" name="PSAD56">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4249" name="Lake">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4250" name="Leigon">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-130,29,364,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4251" name="Liberia 1964">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-90,40,88,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4252" name="Lome">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4253" name="Luzon 1911">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4254" name="Hito XVIII 1963">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=18.38,192.45,96.82,0.056,-0.142,-0.2,-0.0013"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4255" name="Herat North">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-333,-222,114,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4256" name="Mahe 1971">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=41,-220,-134,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4257" name="Makassar">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=-587.8,519.75,145.76,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4258" name="ETRS89">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4259" name="Malongo 1987">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4260" name="Manoca">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-70.9,-151.8,-41.4,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4261" name="Merchich">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=31,146,47,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4262" name="Massawa">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=639,405,60,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4263" name="Minna">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4264" name="Mhast">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-252.95,-4.11,-96.38,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4265" name="Monte Mario">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4266" name="M&apos;poraloko">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4267" name="NAD27">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4268" name="NAD27 Michigan">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378450.047548896"/>
+        <parameter value="b=6356826.621488444"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4269" name="NAD83">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4270" name="Nahrwan 1967">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4271" name="Naparima 1972">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4272" name="NZGD49">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4273" name="NGO 1948">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="towgs84=278.3,93,474.5,7.889,0.05,-6.61,6.21"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4274" name="Datum 73">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4275" name="NTF">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4276" name="NSWC 9Z-2">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4277" name="OSGB 1936">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=airy"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4278" name="OSGB70">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=airy"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4279" name="OS(SN)80">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=airy"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4280" name="Padang">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4281" name="Palestine 1923">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378300.789"/>
+        <parameter value="b=6356566.435"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4282" name="Pointe Noire">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4283" name="GDA94">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4284" name="Pulkovo 1942">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4285" name="Qatar 1974">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4286" name="Qatar 1948">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4287" name="Qornoq">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=164,138,-189,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4288" name="Loma Quintana">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4289" name="Amersfoort">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4291" name="SAD69">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4292" name="Sapper Hill 1943">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-355,21,72,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4293" name="Schwarzeck">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bess_nam"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4294" name="Segora">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4295" name="Serindung">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4296" name="Sudan">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4297" name="Tananarive">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-189,-242,-91,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4298" name="Timbalai 1948">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=evrstSS"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4299" name="TM65">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377340.189"/>
+        <parameter value="b=6356034.447938534"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4300" name="TM75">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377340.189"/>
+        <parameter value="b=6356034.447938534"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4301" name="Tokyo">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4302" name="Trinidad 1903">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378293.63683822"/>
+        <parameter value="b=6356617.979337744"/>
+        <parameter value="towgs84=-61.702,284.488,472.052,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4303" name="TC(1948)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4304" name="Voirol 1875">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-73,-247,227,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4306" name="Bern 1938">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4307" name="Nord Sahara 1959">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4308" name="RT38">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4309" name="Yacare">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-155,171,37,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4310" name="Yoff">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4311" name="Zanderij">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-265,120,-358,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4312" name="MGI">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4313" name="Belge 1972">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4314" name="DHDN">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4315" name="Conakry 1905">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-23,259,-9,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4316" name="Dealul Piscului 1933">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=103.25,-100.4,-307.19,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4317" name="Dealul Piscului 1970">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4318" name="NGN">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4319" name="KUDAMS">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4322" name="WGS 72">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4324" name="WGS 72BE">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4326" name="WGS 84">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4600" name="Anguilla 1957">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4601" name="Antigua 1943">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-255,-15,71,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4602" name="Dominica 1945">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=725,685,536,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4603" name="Grenada 1953">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=72,213.7,93,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4604" name="Montserrat 1958">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=174,359,365,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4605" name="St. Kitts 1955">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=9,183,236,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4606" name="St. Lucia 1955">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-149,128,296,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4607" name="St. Vincent 1945">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4608" name="NAD27(76)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4609" name="NAD27(CGQ77)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4610" name="Xian 1980">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378140"/>
+        <parameter value="b=6356755.288157528"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4611" name="Hong Kong 1980">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-162.619,-276.959,-161.764,0.067753,-2.24365,-1.15883,-1.09425"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4612" name="JGD2000">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4613" name="Segara">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=-404.78,685.68,45.47,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4614" name="QND95">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-119.425,-303.659,-11.0006,1.1643,0.174458,1.09626,3.65706"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4615" name="Porto Santo">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4616" name="Selvagem Grande">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4617" name="NAD83(CSRS)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4801" name="Bern 1898 (Bern)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=bern"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4802" name="Bogota 1975 (Bogota)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="pm=bogota"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4803" name="Lisbon (Lisbon)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="pm=lisbon"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4804" name="Makassar (Jakarta)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=-587.8,519.75,145.76,0,0,0,0"/>
+        <parameter value="pm=jakarta"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4805" name="MGI (Ferro)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=ferro"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4806" name="Monte Mario (Rome)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="pm=rome"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4807" name="NTF (Paris)">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4808" name="Padang (Jakarta)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=jakarta"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4809" name="Belge 1950 (Brussels)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="pm=brussels"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4810" name="Tananarive (Paris)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-189,-242,-91,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4811" name="Voirol 1875 (Paris)">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-73,-247,227,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4813" name="Batavia (Jakarta)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=jakarta"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4814" name="RT38 (Stockholm)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=stockholm"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4815" name="Greek (Athens)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=athens"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4816" name="Carthage (Paris)">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="pm=paris"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4817" name="NGO 1948 (Oslo)">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="towgs84=278.3,93,474.5,7.889,0.05,-6.61,6.21"/>
+        <parameter value="pm=oslo"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4818" name="S-JTSK (Ferro)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=ferro"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4819" name="Nord Sahara 1959 (Paris)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="pm=paris"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4820" name="Segara (Jakarta)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=jakarta"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4901" name="ATF (Paris)">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6376523"/>
+        <parameter value="b=6355862.933255573"/>
+        <parameter value="pm=paris"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4902" name="NDG (Paris)">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6376523"/>
+        <parameter value="b=6355862.933255573"/>
+        <parameter value="pm=paris"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4903" name="Madrid 1870 (Madrid)">
+        <parameter value="proj=longlat"/>
+        <parameter value="a=6378298.3"/>
+        <parameter value="b=6356657.142669562"/>
+        <parameter value="pm=madrid"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="4904" name="Lisbon 1890 (Lisbon)">
+        <parameter value="proj=longlat"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=lisbon"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20004" name="Pulkovo 1995 / Gauss-Kruger zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20005" name="Pulkovo 1995 / Gauss-Kruger zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20006" name="Pulkovo 1995 / Gauss-Kruger zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=6500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20007" name="Pulkovo 1995 / Gauss-Kruger zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=7500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20008" name="Pulkovo 1995 / Gauss-Kruger zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=8500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20009" name="Pulkovo 1995 / Gauss-Kruger zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=9500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20010" name="Pulkovo 1995 / Gauss-Kruger zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=10500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20011" name="Pulkovo 1995 / Gauss-Kruger zone 11">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=11500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20012" name="Pulkovo 1995 / Gauss-Kruger zone 12">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=12500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20013" name="Pulkovo 1995 / Gauss-Kruger zone 13">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=13500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20014" name="Pulkovo 1995 / Gauss-Kruger zone 14">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=14500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20015" name="Pulkovo 1995 / Gauss-Kruger zone 15">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=15500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20016" name="Pulkovo 1995 / Gauss-Kruger zone 16">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=16500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20017" name="Pulkovo 1995 / Gauss-Kruger zone 17">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=17500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20018" name="Pulkovo 1995 / Gauss-Kruger zone 18">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=18500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20019" name="Pulkovo 1995 / Gauss-Kruger zone 19">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=19500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20020" name="Pulkovo 1995 / Gauss-Kruger zone 20">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=20500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20021" name="Pulkovo 1995 / Gauss-Kruger zone 21">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=21500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20022" name="Pulkovo 1995 / Gauss-Kruger zone 22">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=22500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20023" name="Pulkovo 1995 / Gauss-Kruger zone 23">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=23500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20024" name="Pulkovo 1995 / Gauss-Kruger zone 24">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=141"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=24500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20025" name="Pulkovo 1995 / Gauss-Kruger zone 25">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=147"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=25500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20026" name="Pulkovo 1995 / Gauss-Kruger zone 26">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=153"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=26500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20027" name="Pulkovo 1995 / Gauss-Kruger zone 27">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=159"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=27500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20028" name="Pulkovo 1995 / Gauss-Kruger zone 28">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=165"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=28500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20029" name="Pulkovo 1995 / Gauss-Kruger zone 29">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=29500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20030" name="Pulkovo 1995 / Gauss-Kruger zone 30">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=30500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20031" name="Pulkovo 1995 / Gauss-Kruger zone 31">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=31500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20032" name="Pulkovo 1995 / Gauss-Kruger zone 32">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=32500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20064" name="Pulkovo 1995 / Gauss-Kruger 4N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20065" name="Pulkovo 1995 / Gauss-Kruger 5N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20066" name="Pulkovo 1995 / Gauss-Kruger 6N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20067" name="Pulkovo 1995 / Gauss-Kruger 7N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20068" name="Pulkovo 1995 / Gauss-Kruger 8N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20069" name="Pulkovo 1995 / Gauss-Kruger 9N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20070" name="Pulkovo 1995 / Gauss-Kruger 10N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20071" name="Pulkovo 1995 / Gauss-Kruger 11N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20072" name="Pulkovo 1995 / Gauss-Kruger 12N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20073" name="Pulkovo 1995 / Gauss-Kruger 13N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20074" name="Pulkovo 1995 / Gauss-Kruger 14N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20075" name="Pulkovo 1995 / Gauss-Kruger 15N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20076" name="Pulkovo 1995 / Gauss-Kruger 16N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20077" name="Pulkovo 1995 / Gauss-Kruger 17N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20078" name="Pulkovo 1995 / Gauss-Kruger 18N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20079" name="Pulkovo 1995 / Gauss-Kruger 19N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20080" name="Pulkovo 1995 / Gauss-Kruger 20N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20081" name="Pulkovo 1995 / Gauss-Kruger 21N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20082" name="Pulkovo 1995 / Gauss-Kruger 22N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20083" name="Pulkovo 1995 / Gauss-Kruger 23N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20084" name="Pulkovo 1995 / Gauss-Kruger 24N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=141"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20085" name="Pulkovo 1995 / Gauss-Kruger 25N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=147"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20086" name="Pulkovo 1995 / Gauss-Kruger 26N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=153"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20087" name="Pulkovo 1995 / Gauss-Kruger 27N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=159"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20088" name="Pulkovo 1995 / Gauss-Kruger 28N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=165"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20089" name="Pulkovo 1995 / Gauss-Kruger 29N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20090" name="Pulkovo 1995 / Gauss-Kruger 30N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20091" name="Pulkovo 1995 / Gauss-Kruger 31N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20092" name="Pulkovo 1995 / Gauss-Kruger 32N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20137" name="Adindan / UTM zone 37N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20138" name="Adindan / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20248" name="AGD66 / AMG zone 48">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20249" name="AGD66 / AMG zone 49">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20250" name="AGD66 / AMG zone 50">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20251" name="AGD66 / AMG zone 51">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20252" name="AGD66 / AMG zone 52">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20253" name="AGD66 / AMG zone 53">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20254" name="AGD66 / AMG zone 54">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=54"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20255" name="AGD66 / AMG zone 55">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=55"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20256" name="AGD66 / AMG zone 56">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=56"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20257" name="AGD66 / AMG zone 57">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=57"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20258" name="AGD66 / AMG zone 58">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20348" name="AGD84 / AMG zone 48">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20349" name="AGD84 / AMG zone 49">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20350" name="AGD84 / AMG zone 50">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20351" name="AGD84 / AMG zone 51">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20352" name="AGD84 / AMG zone 52">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20353" name="AGD84 / AMG zone 53">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20354" name="AGD84 / AMG zone 54">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=54"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20355" name="AGD84 / AMG zone 55">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=55"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20356" name="AGD84 / AMG zone 56">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=56"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20357" name="AGD84 / AMG zone 57">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=57"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20358" name="AGD84 / AMG zone 58">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="south"/>
+        <parameter value="ellps=aust_SA"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20437" name="Ain el Abd / UTM zone 37N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20438" name="Ain el Abd / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20439" name="Ain el Abd / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20499" name="Ain el Abd / Bahrain Grid">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20538" name="Afgooye / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-43,-163,45,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20539" name="Afgooye / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="towgs84=-43,-163,45,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20790" name="Lisbon (Lisbon)/Portuguese National Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=39.66666666666666"/>
+        <parameter value="lon_0=-8.131906111111112"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="pm=lisbon"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20791" name="Lisbon (Lisbon)/Portuguese Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=39.66666666666666"/>
+        <parameter value="lon_0=-8.131906111111112"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="pm=lisbon"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20822" name="Aratu / UTM zone 22S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20823" name="Aratu / UTM zone 23S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20824" name="Aratu / UTM zone 24S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=24"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20934" name="Arc 1950 / UTM zone 34S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="south"/>
+        <parameter value="a=6378249.145"/>
+        <parameter value="b=6356514.966398753"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20935" name="Arc 1950 / UTM zone 35S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="south"/>
+        <parameter value="a=6378249.145"/>
+        <parameter value="b=6356514.966398753"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="20936" name="Arc 1950 / UTM zone 36S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="south"/>
+        <parameter value="a=6378249.145"/>
+        <parameter value="b=6356514.966398753"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21035" name="Arc 1960 / UTM zone 35S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="south"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21036" name="Arc 1960 / UTM zone 36S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="south"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21037" name="Arc 1960 / UTM zone 37S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="south"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21095" name="Arc 1960 / UTM zone 35N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21096" name="Arc 1960 / UTM zone 36N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21097" name="Arc 1960 / UTM zone 37N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21100" name="Batavia (Jakarta) / NEIEZ">
+        <parameter value="proj=merc"/>
+        <parameter value="lat_ts=0"/>
+        <parameter value="lon_0=216.8077194444444"/>
+        <parameter value="k=0.997000"/>
+        <parameter value="x_0=3900000"/>
+        <parameter value="y_0=900000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=jakarta"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21148" name="Batavia / UTM zone 48S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="south"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21149" name="Batavia / UTM zone 49S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="south"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21150" name="Batavia / UTM zone 50S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="south"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21291" name="Barbados 1938 / British West Indies Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-62"/>
+        <parameter value="k=0.999500"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21292" name="Barbados 1938 / Barbados National Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=13.17638888888889"/>
+        <parameter value="lon_0=-59.55972222222222"/>
+        <parameter value="k=0.999999"/>
+        <parameter value="x_0=30000"/>
+        <parameter value="y_0=75000"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21413" name="Beijing 1954 / Gauss-Kruger zone 13">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=13500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21414" name="Beijing 1954 / Gauss-Kruger zone 14">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=14500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21415" name="Beijing 1954 / Gauss-Kruger zone 15">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=15500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21416" name="Beijing 1954 / Gauss-Kruger zone 16">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=16500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21417" name="Beijing 1954 / Gauss-Kruger zone 17">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=17500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21418" name="Beijing 1954 / Gauss-Kruger zone 18">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=18500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21419" name="Beijing 1954 / Gauss-Kruger zone 19">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=19500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21420" name="Beijing 1954 / Gauss-Kruger zone 20">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=20500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21421" name="Beijing 1954 / Gauss-Kruger zone 21">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=21500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21422" name="Beijing 1954 / Gauss-Kruger zone 22">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=22500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21423" name="Beijing 1954 / Gauss-Kruger zone 23">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=23500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21453" name="Beijing 1954 / Gauss-Kruger CM 75E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21454" name="Beijing 1954 / Gauss-Kruger CM 81E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21455" name="Beijing 1954 / Gauss-Kruger CM 87E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21456" name="Beijing 1954 / Gauss-Kruger CM 93E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21457" name="Beijing 1954 / Gauss-Kruger CM 99E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21458" name="Beijing 1954 / Gauss-Kruger CM 105E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21459" name="Beijing 1954 / Gauss-Kruger CM 111E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21460" name="Beijing 1954 / Gauss-Kruger CM 117E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21461" name="Beijing 1954 / Gauss-Kruger CM 123E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21462" name="Beijing 1954 / Gauss-Kruger CM 129E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21463" name="Beijing 1954 / Gauss-Kruger CM 135E">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21473" name="Beijing 1954 / Gauss-Kruger 13N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21474" name="Beijing 1954 / Gauss-Kruger 14N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21475" name="Beijing 1954 / Gauss-Kruger 15N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21476" name="Beijing 1954 / Gauss-Kruger 16N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21477" name="Beijing 1954 / Gauss-Kruger 17N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21478" name="Beijing 1954 / Gauss-Kruger 18N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21479" name="Beijing 1954 / Gauss-Kruger 19N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21480" name="Beijing 1954 / Gauss-Kruger 20N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21481" name="Beijing 1954 / Gauss-Kruger 21N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21482" name="Beijing 1954 / Gauss-Kruger 22N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21483" name="Beijing 1954 / Gauss-Kruger 23N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21500" name="Belge 1950 (Brussels) / Belge Lambert 50">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49.83333333333334"/>
+        <parameter value="lat_2=51.16666666666666"/>
+        <parameter value="lat_0=90"/>
+        <parameter value="lon_0=4.367975"/>
+        <parameter value="x_0=150000"/>
+        <parameter value="y_0=5400000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="pm=brussels"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21817" name="Bogota 1975 / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21818" name="Bogota 1975 / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21891" name="Bogota 1975 / Colombia West zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=4.599047222222222"/>
+        <parameter value="lon_0=-77.08091666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21892" name="Bogota 1975 / Colombia Bogota zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=4.599047222222222"/>
+        <parameter value="lon_0=-74.08091666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21893" name="Bogota 1975 / Colombia East Central zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=4.599047222222222"/>
+        <parameter value="lon_0=-71.08091666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="21894" name="Bogota 1975 / Colombia East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=4.599047222222222"/>
+        <parameter value="lon_0=-68.08091666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22032" name="Camacupa / UTM zone 32S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="south"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22033" name="Camacupa / UTM zone 33S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="south"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22091" name="Camacupa / TM 11.30 SE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=11.5"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=10000000"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22092" name="Camacupa / TM 12 SE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=12"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=10000000"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22191" name="Campo Inchauspe / Argentina 1">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lon_0=-72"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22192" name="Campo Inchauspe / Argentina 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lon_0=-69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22193" name="Campo Inchauspe / Argentina 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lon_0=-66"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22194" name="Campo Inchauspe / Argentina 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lon_0=-63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22195" name="Campo Inchauspe / Argentina 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lon_0=-60"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22196" name="Campo Inchauspe / Argentina 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lon_0=-57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=6500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22197" name="Campo Inchauspe / Argentina 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lon_0=-54"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=7500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22234" name="Cape / UTM zone 34S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="south"/>
+        <parameter value="a=6378249.145"/>
+        <parameter value="b=6356514.966398753"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22235" name="Cape / UTM zone 35S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="south"/>
+        <parameter value="a=6378249.145"/>
+        <parameter value="b=6356514.966398753"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22236" name="Cape / UTM zone 36S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="south"/>
+        <parameter value="a=6378249.145"/>
+        <parameter value="b=6356514.966398753"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22332" name="Carthage / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22391" name="Carthage / Nord Tunisie">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=9.9"/>
+        <parameter value="k_0=0.999625544"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22392" name="Carthage / Sud Tunisie">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.3"/>
+        <parameter value="lat_0=33.3"/>
+        <parameter value="lon_0=9.9"/>
+        <parameter value="k_0=0.999625769"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22523" name="Corrego Alegre / UTM zone 23S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-206,172,-6,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22524" name="Corrego Alegre / UTM zone 24S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=24"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-206,172,-6,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22700" name="Deir ez Zor / Levant Zone">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=34.65"/>
+        <parameter value="lat_0=34.65"/>
+        <parameter value="lon_0=37.35"/>
+        <parameter value="k_0=0.9996256"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22770" name="Deir ez Zor / Syria Lambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=34.65"/>
+        <parameter value="lat_0=34.65"/>
+        <parameter value="lon_0=37.35"/>
+        <parameter value="k_0=0.9996256"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22780" name="Deir ez Zor / Levant Stereographic">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=34.2"/>
+        <parameter value="lon_0=39.15"/>
+        <parameter value="k=0.999534"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22832" name="Douala / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22991" name="Egypt 1907 / Blue Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=35"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=1100000"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22992" name="Egypt 1907 / Red Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=31"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=615000"/>
+        <parameter value="y_0=810000"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22993" name="Egypt 1907 / Purple Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=200000"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="22994" name="Egypt 1907 / Extended Purple Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=1200000"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23028" name="ED50 / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23029" name="ED50 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23030" name="ED50 / UTM zone 30N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23031" name="ED50 / UTM zone 31N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23032" name="ED50 / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23033" name="ED50 / UTM zone 33N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23034" name="ED50 / UTM zone 34N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23035" name="ED50 / UTM zone 35N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23036" name="ED50 / UTM zone 36N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23037" name="ED50 / UTM zone 37N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23038" name="ED50 / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23090" name="ED50 / TM 0 N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=0"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23095" name="ED50 / TM 5 NE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=5"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23239" name="Fahud / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23240" name="Fahud / UTM zone 40N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23433" name="Garoua / UTM zone 33N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23846" name="ID74 / UTM zone 46N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23847" name="ID74 / UTM zone 47N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23848" name="ID74 / UTM zone 48N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23849" name="ID74 / UTM zone 49N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23850" name="ID74 / UTM zone 50N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23851" name="ID74 / UTM zone 51N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23852" name="ID74 / UTM zone 52N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23853" name="ID74 / UTM zone 53N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23886" name="ID74 / UTM zone 46S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="south"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23887" name="ID74 / UTM zone 47S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="south"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23888" name="ID74 / UTM zone 48S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="south"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23889" name="ID74 / UTM zone 49S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="south"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23890" name="ID74 / UTM zone 50S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="south"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23891" name="ID74 / UTM zone 51S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="south"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23892" name="ID74 / UTM zone 52S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="south"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23893" name="ID74 / UTM zone 53S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="south"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23894" name="ID74 / UTM zone 54S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=54"/>
+        <parameter value="south"/>
+        <parameter value="a=6378160"/>
+        <parameter value="b=6356774.50408554"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23946" name="Indian 1954 / UTM zone 46N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="towgs84=217,823,299,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23947" name="Indian 1954 / UTM zone 47N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="towgs84=217,823,299,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="23948" name="Indian 1954 / UTM zone 48N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="towgs84=217,823,299,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24047" name="Indian 1975 / UTM zone 47N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24048" name="Indian 1975 / UTM zone 48N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24100" name="Jamaica 1875 / Jamaica (Old Grid)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=18"/>
+        <parameter value="lat_0=18"/>
+        <parameter value="lon_0=-77"/>
+        <parameter value="k_0=1"/>
+        <parameter value="x_0=167638.49575"/>
+        <parameter value="y_0=121918.906"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="to_meter=0.304797265"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24200" name="JAD69 / Jamaica National Grid">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=18"/>
+        <parameter value="lat_0=18"/>
+        <parameter value="lon_0=-77"/>
+        <parameter value="k_0=1"/>
+        <parameter value="x_0=250000"/>
+        <parameter value="y_0=150000"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24305" name="Kalianpur 1937 / UTM zone 45N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=45"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24306" name="Kalianpur 1937 / UTM zone 46N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24311" name="Kalianpur 1962 / UTM zone 41N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=41"/>
+        <parameter value="a=6377301.243"/>
+        <parameter value="b=6356100.230165385"/>
+        <parameter value="towgs84=283,682,231,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24312" name="Kalianpur 1962 / UTM zone 42N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=42"/>
+        <parameter value="a=6377301.243"/>
+        <parameter value="b=6356100.230165385"/>
+        <parameter value="towgs84=283,682,231,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24313" name="Kalianpur 1962 / UTM zone 43N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=43"/>
+        <parameter value="a=6377301.243"/>
+        <parameter value="b=6356100.230165385"/>
+        <parameter value="towgs84=283,682,231,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24342" name="Kalianpur 1975 / UTM zone 42N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=42"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24343" name="Kalianpur 1975 / UTM zone 43N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=43"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24344" name="Kalianpur 1975 / UTM zone 44N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=44"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24345" name="Kalianpur 1975 / UTM zone 45N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=45"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24346" name="Kalianpur 1975 / UTM zone 46N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24347" name="Kalianpur 1975 / UTM zone 47N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24370" name="Kalianpur 1880 / India zone 0">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.5"/>
+        <parameter value="lat_0=39.5"/>
+        <parameter value="lon_0=68"/>
+        <parameter value="k_0=0.99846154"/>
+        <parameter value="x_0=2153865.73916853"/>
+        <parameter value="y_0=2368292.194628102"/>
+        <parameter value="a=6377299.36559538"/>
+        <parameter value="b=6356098.357204817"/>
+        <parameter value="to_meter=0.9143985307444408"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24371" name="Kalianpur 1880 / India zone I">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=32.5"/>
+        <parameter value="lat_0=32.5"/>
+        <parameter value="lon_0=68"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743195.592233322"/>
+        <parameter value="y_0=914398.5307444407"/>
+        <parameter value="a=6377299.36559538"/>
+        <parameter value="b=6356098.357204817"/>
+        <parameter value="to_meter=0.9143985307444408"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24372" name="Kalianpur 1880 / India zone IIa">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=26"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=74"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743195.592233322"/>
+        <parameter value="y_0=914398.5307444407"/>
+        <parameter value="a=6377299.36559538"/>
+        <parameter value="b=6356098.357204817"/>
+        <parameter value="to_meter=0.9143985307444408"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24373" name="Kalianpur 1880 / India zone III">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=19"/>
+        <parameter value="lat_0=19"/>
+        <parameter value="lon_0=80"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743195.592233322"/>
+        <parameter value="y_0=914398.5307444407"/>
+        <parameter value="a=6377299.36559538"/>
+        <parameter value="b=6356098.357204817"/>
+        <parameter value="to_meter=0.9143985307444408"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24374" name="Kalianpur 1880 / India zone IV">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=12"/>
+        <parameter value="lat_0=12"/>
+        <parameter value="lon_0=80"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743195.592233322"/>
+        <parameter value="y_0=914398.5307444407"/>
+        <parameter value="a=6377299.36559538"/>
+        <parameter value="b=6356098.357204817"/>
+        <parameter value="to_meter=0.9143985307444408"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24375" name="Kalianpur 1937 / India zone IIb">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=26"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743185.69"/>
+        <parameter value="y_0=914395.23"/>
+        <parameter value="a=6377276.345"/>
+        <parameter value="b=6356075.413140239"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24376" name="Kalianpur 1962 / India zone I">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=32.5"/>
+        <parameter value="lat_0=32.5"/>
+        <parameter value="lon_0=68"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743196.4"/>
+        <parameter value="y_0=914398.8"/>
+        <parameter value="a=6377301.243"/>
+        <parameter value="b=6356100.230165385"/>
+        <parameter value="towgs84=283,682,231,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24377" name="Kalianpur 1962 / India zone IIa">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=26"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=74"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743196.4"/>
+        <parameter value="y_0=914398.8"/>
+        <parameter value="a=6377301.243"/>
+        <parameter value="b=6356100.230165385"/>
+        <parameter value="towgs84=283,682,231,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24378" name="Kalianpur 1975 / India zone I">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=32.5"/>
+        <parameter value="lat_0=32.5"/>
+        <parameter value="lon_0=68"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743195.5"/>
+        <parameter value="y_0=914398.5"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24379" name="Kalianpur 1975 / India zone IIa">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=26"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=74"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743195.5"/>
+        <parameter value="y_0=914398.5"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24380" name="Kalianpur 1975 / India zone IIb">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=26"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743195.5"/>
+        <parameter value="y_0=914398.5"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24381" name="Kalianpur 1975 / India zone III">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=19"/>
+        <parameter value="lat_0=19"/>
+        <parameter value="lon_0=80"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743195.5"/>
+        <parameter value="y_0=914398.5"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24382" name="Kalianpur 1880 / India zone IIb">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=26"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=90"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743195.592233322"/>
+        <parameter value="y_0=914398.5307444407"/>
+        <parameter value="a=6377299.36559538"/>
+        <parameter value="b=6356098.357204817"/>
+        <parameter value="to_meter=0.9143985307444408"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24383" name="Kalianpur 1975 / India zone IV">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=12"/>
+        <parameter value="lat_0=12"/>
+        <parameter value="lon_0=80"/>
+        <parameter value="k_0=0.99878641"/>
+        <parameter value="x_0=2743195.5"/>
+        <parameter value="y_0=914398.5"/>
+        <parameter value="a=6377299.151"/>
+        <parameter value="b=6356098.145120132"/>
+        <parameter value="towgs84=295,736,257,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24500" name="Kertau / Singapore Grid">
+        <parameter value="proj=cass"/>
+        <parameter value="lat_0=1.287646666666667"/>
+        <parameter value="lon_0=103.8530022222222"/>
+        <parameter value="x_0=30000"/>
+        <parameter value="y_0=30000"/>
+        <parameter value="a=6377304.063"/>
+        <parameter value="b=6356103.038993155"/>
+        <parameter value="towgs84=-11,851,5,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24547" name="Kertau / UTM zone 47N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="a=6377304.063"/>
+        <parameter value="b=6356103.038993155"/>
+        <parameter value="towgs84=-11,851,5,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24548" name="Kertau / UTM zone 48N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="a=6377304.063"/>
+        <parameter value="b=6356103.038993155"/>
+        <parameter value="towgs84=-11,851,5,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24571" name="Kertau / R.S.O. Malaya (ch)">
+        <parameter value="proj=omerc"/>
+        <parameter value="lat_0=4"/>
+        <parameter value="lonc=102.25"/>
+        <parameter value="alpha=323.0257905"/>
+        <parameter value="k=0.99984"/>
+        <parameter value="x_0=804671.2997750348"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6377304.063"/>
+        <parameter value="b=6356103.038993155"/>
+        <parameter value="towgs84=-11,851,5,0,0,0,0"/>
+        <parameter value="to_meter=20.11678249437587"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24600" name="KOC Lambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=32.5"/>
+        <parameter value="lat_0=32.5"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k_0=0.9987864078000001"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=1166200"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24718" name="La Canoa / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-273.5,110.6,-357.9,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24719" name="La Canoa / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-273.5,110.6,-357.9,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24720" name="La Canoa / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-273.5,110.6,-357.9,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24818" name="PSAD56 / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24819" name="PSAD56 / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24820" name="PSAD56 / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24821" name="PSAD56 / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24877" name="PSAD56 / UTM zone 17S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24878" name="PSAD56 / UTM zone 18S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24879" name="PSAD56 / UTM zone 19S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24880" name="PSAD56 / UTM zone 20S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24882" name="PSAD56 / UTM zone 22S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24891" name="PSAD56 / Peru west zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-6"/>
+        <parameter value="lon_0=-80.5"/>
+        <parameter value="k=0.999830"/>
+        <parameter value="x_0=222000"/>
+        <parameter value="y_0=1426834.743"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24892" name="PSAD56 / Peru central zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-9.5"/>
+        <parameter value="lon_0=-76"/>
+        <parameter value="k=0.999330"/>
+        <parameter value="x_0=720000"/>
+        <parameter value="y_0=1039979.159"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="24893" name="PSAD56 / Peru east zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-9.5"/>
+        <parameter value="lon_0=-70.5"/>
+        <parameter value="k=0.999530"/>
+        <parameter value="x_0=1324000"/>
+        <parameter value="y_0=1040084.558"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25000" name="Leigon / Ghana Metre Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=4.666666666666667"/>
+        <parameter value="lon_0=-1"/>
+        <parameter value="k=0.999750"/>
+        <parameter value="x_0=274319.51"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="towgs84=-130,29,364,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25231" name="Lome / UTM zone 31N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25391" name="Luzon 1911 / Philippines zone I">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25392" name="Luzon 1911 / Philippines zone II">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=119"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25393" name="Luzon 1911 / Philippines zone III">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=121"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25394" name="Luzon 1911 / Philippines zone IV">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25395" name="Luzon 1911 / Philippines zone V">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=125"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25700" name="Makassar (Jakarta) / NEIEZ">
+        <parameter value="proj=merc"/>
+        <parameter value="lat_ts=0"/>
+        <parameter value="lon_0=216.8077194444444"/>
+        <parameter value="k=0.997000"/>
+        <parameter value="x_0=3900000"/>
+        <parameter value="y_0=900000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=-587.8,519.75,145.76,0,0,0,0"/>
+        <parameter value="pm=jakarta"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25828" name="ETRS89 / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25829" name="ETRS89 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25830" name="ETRS89 / UTM zone 30N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25831" name="ETRS89 / UTM zone 31N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25832" name="ETRS89 / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25833" name="ETRS89 / UTM zone 33N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25834" name="ETRS89 / UTM zone 34N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25835" name="ETRS89 / UTM zone 35N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25836" name="ETRS89 / UTM zone 36N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25837" name="ETRS89 / UTM zone 37N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25838" name="ETRS89 / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25884" name="ETRS89 / TM Baltic93">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="25932" name="Malongo 1987 / UTM zone 32S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26191" name="Merchich / Nord Maroc">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.3"/>
+        <parameter value="lat_0=33.3"/>
+        <parameter value="lon_0=-5.4"/>
+        <parameter value="k_0=0.999625769"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=31,146,47,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26192" name="Merchich / Sud Maroc">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=29.7"/>
+        <parameter value="lat_0=29.7"/>
+        <parameter value="lon_0=-5.4"/>
+        <parameter value="k_0=0.9996155960000001"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=31,146,47,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26193" name="Merchich / Sahara">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=26.1"/>
+        <parameter value="lat_0=26.1"/>
+        <parameter value="lon_0=-5.4"/>
+        <parameter value="k_0=0.9996"/>
+        <parameter value="x_0=1200000"/>
+        <parameter value="y_0=400000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=31,146,47,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26237" name="Massawa / UTM zone 37N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="towgs84=639,405,60,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26331" name="Minna / UTM zone 31N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26332" name="Minna / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26391" name="Minna / Nigeria West Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=4"/>
+        <parameter value="lon_0=4.5"/>
+        <parameter value="k=0.999750"/>
+        <parameter value="x_0=230738.26"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26392" name="Minna / Nigeria Mid Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=4"/>
+        <parameter value="lon_0=8.5"/>
+        <parameter value="k=0.999750"/>
+        <parameter value="x_0=670553.98"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26393" name="Minna / Nigeria East Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=4"/>
+        <parameter value="lon_0=12.5"/>
+        <parameter value="k=0.999750"/>
+        <parameter value="x_0=1110369.7"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26432" name="Mhast / UTM zone 32S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-252.95,-4.11,-96.38,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26591" name="Monte Mario (Rome) / Italy zone 1">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21.45233333333333"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="pm=rome"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26592" name="Monte Mario (Rome) / Italy zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27.45233333333333"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=2520000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="pm=rome"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26632" name="M&apos;poraloko / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26692" name="M&apos;poraloko / UTM zone 32S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="south"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26703" name="NAD27 / UTM zone 3N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=3"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26704" name="NAD27 / UTM zone 4N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=4"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26705" name="NAD27 / UTM zone 5N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=5"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26706" name="NAD27 / UTM zone 6N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=6"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26707" name="NAD27 / UTM zone 7N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=7"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26708" name="NAD27 / UTM zone 8N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=8"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26709" name="NAD27 / UTM zone 9N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=9"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26710" name="NAD27 / UTM zone 10N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=10"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26711" name="NAD27 / UTM zone 11N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=11"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26712" name="NAD27 / UTM zone 12N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=12"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26713" name="NAD27 / UTM zone 13N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=13"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26714" name="NAD27 / UTM zone 14N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=14"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26715" name="NAD27 / UTM zone 15N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=15"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26716" name="NAD27 / UTM zone 16N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=16"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26717" name="NAD27 / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26718" name="NAD27 / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26719" name="NAD27 / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26720" name="NAD27 / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26721" name="NAD27 / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26722" name="NAD27 / UTM zone 22N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26729" name="NAD27 / Alabama East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30.5"/>
+        <parameter value="lon_0=-85.83333333333333"/>
+        <parameter value="k=0.999960"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26730" name="NAD27 / Alabama West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-87.5"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26731" name="NAD27 / Alaska zone 1">
+        <parameter value="proj=omerc"/>
+        <parameter value="lat_0=57"/>
+        <parameter value="lonc=-133.6666666666667"/>
+        <parameter value="alpha=323.1301023611111"/>
+        <parameter value="k=0.9999"/>
+        <parameter value="x_0=5000000.001016002"/>
+        <parameter value="y_0=-5000000.001016002"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26732" name="NAD27 / Alaska zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-142"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26733" name="NAD27 / Alaska zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-146"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26734" name="NAD27 / Alaska zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-150"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26735" name="NAD27 / Alaska zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-154"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26736" name="NAD27 / Alaska zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-158"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26737" name="NAD27 / Alaska zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-162"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=213360.4267208534"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26738" name="NAD27 / Alaska zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-166"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26739" name="NAD27 / Alaska zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-170"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=182880.3657607315"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26740" name="NAD27 / Alaska zone 10">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=53.83333333333334"/>
+        <parameter value="lat_2=51.83333333333334"/>
+        <parameter value="lat_0=51"/>
+        <parameter value="lon_0=-176"/>
+        <parameter value="x_0=914401.8288036576"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26741" name="NAD27 / California zone I">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.66666666666666"/>
+        <parameter value="lat_2=40"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-122"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26742" name="NAD27 / California zone II">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.83333333333334"/>
+        <parameter value="lat_2=38.33333333333334"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-122"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26743" name="NAD27 / California zone III">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.43333333333333"/>
+        <parameter value="lat_2=37.06666666666667"/>
+        <parameter value="lat_0=36.5"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26744" name="NAD27 / California zone IV">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.25"/>
+        <parameter value="lat_2=36"/>
+        <parameter value="lat_0=35.33333333333334"/>
+        <parameter value="lon_0=-119"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26745" name="NAD27 / California zone V">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.46666666666667"/>
+        <parameter value="lat_2=34.03333333333333"/>
+        <parameter value="lat_0=33.5"/>
+        <parameter value="lon_0=-118"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26746" name="NAD27 / California zone VI">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.88333333333333"/>
+        <parameter value="lat_2=32.78333333333333"/>
+        <parameter value="lat_0=32.16666666666666"/>
+        <parameter value="lon_0=-116.25"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26747" name="NAD27 / California zone VII">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=34.41666666666666"/>
+        <parameter value="lat_2=33.86666666666667"/>
+        <parameter value="lat_0=34.13333333333333"/>
+        <parameter value="lon_0=-118.3333333333333"/>
+        <parameter value="x_0=1276106.450596901"/>
+        <parameter value="y_0=127079.524511049"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26748" name="NAD27 / Arizona East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-110.1666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26749" name="NAD27 / Arizona Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-111.9166666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26750" name="NAD27 / Arizona West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-113.75"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26751" name="NAD27 / Arkansas North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.23333333333333"/>
+        <parameter value="lat_2=34.93333333333333"/>
+        <parameter value="lat_0=34.33333333333334"/>
+        <parameter value="lon_0=-92"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26752" name="NAD27 / Arkansas South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=34.76666666666667"/>
+        <parameter value="lat_2=33.3"/>
+        <parameter value="lat_0=32.66666666666666"/>
+        <parameter value="lon_0=-92"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26753" name="NAD27 / Colorado North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.71666666666667"/>
+        <parameter value="lat_2=40.78333333333333"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26754" name="NAD27 / Colorado Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.75"/>
+        <parameter value="lat_2=38.45"/>
+        <parameter value="lat_0=37.83333333333334"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26755" name="NAD27 / Colorado South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.43333333333333"/>
+        <parameter value="lat_2=37.23333333333333"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26756" name="NAD27 / Connecticut">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.86666666666667"/>
+        <parameter value="lat_2=41.2"/>
+        <parameter value="lat_0=40.83333333333334"/>
+        <parameter value="lon_0=-72.75"/>
+        <parameter value="x_0=182880.3657607315"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26757" name="NAD27 / Delaware">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=-75.41666666666667"/>
+        <parameter value="k=0.999995"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26758" name="NAD27 / Florida East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.33333333333333"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26759" name="NAD27 / Florida West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.33333333333333"/>
+        <parameter value="lon_0=-82"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26760" name="NAD27 / Florida North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.75"/>
+        <parameter value="lat_2=29.58333333333333"/>
+        <parameter value="lat_0=29"/>
+        <parameter value="lon_0=-84.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26766" name="NAD27 / Georgia East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-82.16666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26767" name="NAD27 / Georgia West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-84.16666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26768" name="NAD27 / Idaho East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-112.1666666666667"/>
+        <parameter value="k=0.999947"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26769" name="NAD27 / Idaho Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-114"/>
+        <parameter value="k=0.999947"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26770" name="NAD27 / Idaho West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-115.75"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26771" name="NAD27 / Illinois East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-88.33333333333333"/>
+        <parameter value="k=0.999975"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26772" name="NAD27 / Illinois West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-90.16666666666667"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26773" name="NAD27 / Indiana East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-85.66666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26774" name="NAD27 / Indiana West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-87.08333333333333"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26775" name="NAD27 / Iowa North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=43.26666666666667"/>
+        <parameter value="lat_2=42.06666666666667"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-93.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26776" name="NAD27 / Iowa South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.78333333333333"/>
+        <parameter value="lat_2=40.61666666666667"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-93.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26777" name="NAD27 / Kansas North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.78333333333333"/>
+        <parameter value="lat_2=38.71666666666667"/>
+        <parameter value="lat_0=38.33333333333334"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26778" name="NAD27 / Kansas South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.56666666666667"/>
+        <parameter value="lat_2=37.26666666666667"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26779" name="NAD27 / Kentucky North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.96666666666667"/>
+        <parameter value="lat_2=38.96666666666667"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-84.25"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26780" name="NAD27 / Kentucky South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.73333333333333"/>
+        <parameter value="lat_2=37.93333333333333"/>
+        <parameter value="lat_0=36.33333333333334"/>
+        <parameter value="lon_0=-85.75"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26781" name="NAD27 / Louisiana North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=31.16666666666667"/>
+        <parameter value="lat_2=32.66666666666666"/>
+        <parameter value="lat_0=30.66666666666667"/>
+        <parameter value="lon_0=-92.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26782" name="NAD27 / Louisiana South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=29.3"/>
+        <parameter value="lat_2=30.7"/>
+        <parameter value="lat_0=28.66666666666667"/>
+        <parameter value="lon_0=-91.33333333333333"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26783" name="NAD27 / Maine East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=43.83333333333334"/>
+        <parameter value="lon_0=-68.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26784" name="NAD27 / Maine West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=42.83333333333334"/>
+        <parameter value="lon_0=-70.16666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26785" name="NAD27 / Maryland">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.3"/>
+        <parameter value="lat_2=39.45"/>
+        <parameter value="lat_0=37.83333333333334"/>
+        <parameter value="lon_0=-77"/>
+        <parameter value="x_0=243840.4876809754"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26786" name="NAD27 / Massachusetts Mainland">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.71666666666667"/>
+        <parameter value="lat_2=42.68333333333333"/>
+        <parameter value="lat_0=41"/>
+        <parameter value="lon_0=-71.5"/>
+        <parameter value="x_0=182880.3657607315"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26787" name="NAD27 / Massachusetts Island">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.28333333333333"/>
+        <parameter value="lat_2=41.48333333333333"/>
+        <parameter value="lat_0=41"/>
+        <parameter value="lon_0=-70.5"/>
+        <parameter value="x_0=60960.12192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26791" name="NAD27 / Minnesota North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.03333333333333"/>
+        <parameter value="lat_2=48.63333333333333"/>
+        <parameter value="lat_0=46.5"/>
+        <parameter value="lon_0=-93.09999999999999"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26792" name="NAD27 / Minnesota Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.61666666666667"/>
+        <parameter value="lat_2=47.05"/>
+        <parameter value="lat_0=45"/>
+        <parameter value="lon_0=-94.25"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26793" name="NAD27 / Minnesota South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=43.78333333333333"/>
+        <parameter value="lat_2=45.21666666666667"/>
+        <parameter value="lat_0=43"/>
+        <parameter value="lon_0=-94"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26794" name="NAD27 / Mississippi East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=29.66666666666667"/>
+        <parameter value="lon_0=-88.83333333333333"/>
+        <parameter value="k=0.999960"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26795" name="NAD27 / Mississippi West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30.5"/>
+        <parameter value="lon_0=-90.33333333333333"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26796" name="NAD27 / Missouri East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=35.83333333333334"/>
+        <parameter value="lon_0=-90.5"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26797" name="NAD27 / Missouri Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=35.83333333333334"/>
+        <parameter value="lon_0=-92.5"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26798" name="NAD27 / Missouri West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36.16666666666666"/>
+        <parameter value="lon_0=-94.5"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26801" name="NAD Michigan / Michigan East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-83.66666666666667"/>
+        <parameter value="k=0.999943"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378450.047548896"/>
+        <parameter value="b=6356826.621488444"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26802" name="NAD Michigan / Michigan Old Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-85.75"/>
+        <parameter value="k=0.999909"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378450.047548896"/>
+        <parameter value="b=6356826.621488444"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26803" name="NAD Michigan / Michigan West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-88.75"/>
+        <parameter value="k=0.999909"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378450.047548896"/>
+        <parameter value="b=6356826.621488444"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26811" name="NAD Michigan / Michigan North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.48333333333333"/>
+        <parameter value="lat_2=47.08333333333334"/>
+        <parameter value="lat_0=44.78333333333333"/>
+        <parameter value="lon_0=-87"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378450.047548896"/>
+        <parameter value="b=6356826.621488444"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26812" name="NAD Michigan / Michigan Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.18333333333333"/>
+        <parameter value="lat_2=45.7"/>
+        <parameter value="lat_0=43.31666666666667"/>
+        <parameter value="lon_0=-84.33333333333333"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378450.047548896"/>
+        <parameter value="b=6356826.621488444"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26813" name="NAD Michigan / Michigan South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.1"/>
+        <parameter value="lat_2=43.66666666666666"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-84.33333333333333"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6378450.047548896"/>
+        <parameter value="b=6356826.621488444"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26903" name="NAD83 / UTM zone 3N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=3"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26904" name="NAD83 / UTM zone 4N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=4"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26905" name="NAD83 / UTM zone 5N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=5"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26906" name="NAD83 / UTM zone 6N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=6"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26907" name="NAD83 / UTM zone 7N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=7"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26908" name="NAD83 / UTM zone 8N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=8"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26909" name="NAD83 / UTM zone 9N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=9"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26910" name="NAD83 / UTM zone 10N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=10"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26911" name="NAD83 / UTM zone 11N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=11"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26912" name="NAD83 / UTM zone 12N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=12"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26913" name="NAD83 / UTM zone 13N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=13"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26914" name="NAD83 / UTM zone 14N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=14"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26915" name="NAD83 / UTM zone 15N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=15"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26916" name="NAD83 / UTM zone 16N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=16"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26917" name="NAD83 / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26918" name="NAD83 / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26919" name="NAD83 / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26920" name="NAD83 / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26921" name="NAD83 / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26922" name="NAD83 / UTM zone 22N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26923" name="NAD83 / UTM zone 23N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26929" name="NAD83 / Alabama East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30.5"/>
+        <parameter value="lon_0=-85.83333333333333"/>
+        <parameter value="k=0.999960"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26930" name="NAD83 / Alabama West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-87.5"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26931" name="NAD83 / Alaska zone 1">
+        <parameter value="proj=omerc"/>
+        <parameter value="lat_0=57"/>
+        <parameter value="lonc=-133.6666666666667"/>
+        <parameter value="alpha=323.1301023611111"/>
+        <parameter value="k=0.9999"/>
+        <parameter value="x_0=5000000"/>
+        <parameter value="y_0=-5000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26932" name="NAD83 / Alaska zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-142"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26933" name="NAD83 / Alaska zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-146"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26934" name="NAD83 / Alaska zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-150"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26935" name="NAD83 / Alaska zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-154"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26936" name="NAD83 / Alaska zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-158"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26937" name="NAD83 / Alaska zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-162"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26938" name="NAD83 / Alaska zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-166"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26939" name="NAD83 / Alaska zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=54"/>
+        <parameter value="lon_0=-170"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26940" name="NAD83 / Alaska zone 10">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=53.83333333333334"/>
+        <parameter value="lat_2=51.83333333333334"/>
+        <parameter value="lat_0=51"/>
+        <parameter value="lon_0=-176"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26941" name="NAD83 / California zone 1">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.66666666666666"/>
+        <parameter value="lat_2=40"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-122"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26942" name="NAD83 / California zone 2">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.83333333333334"/>
+        <parameter value="lat_2=38.33333333333334"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-122"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26943" name="NAD83 / California zone 3">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.43333333333333"/>
+        <parameter value="lat_2=37.06666666666667"/>
+        <parameter value="lat_0=36.5"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26944" name="NAD83 / California zone 4">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.25"/>
+        <parameter value="lat_2=36"/>
+        <parameter value="lat_0=35.33333333333334"/>
+        <parameter value="lon_0=-119"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26945" name="NAD83 / California zone 5">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.46666666666667"/>
+        <parameter value="lat_2=34.03333333333333"/>
+        <parameter value="lat_0=33.5"/>
+        <parameter value="lon_0=-118"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26946" name="NAD83 / California zone 6">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.88333333333333"/>
+        <parameter value="lat_2=32.78333333333333"/>
+        <parameter value="lat_0=32.16666666666666"/>
+        <parameter value="lon_0=-116.25"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26948" name="NAD83 / Arizona East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-110.1666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26949" name="NAD83 / Arizona Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-111.9166666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26950" name="NAD83 / Arizona West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-113.75"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=213360"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26951" name="NAD83 / Arkansas North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.23333333333333"/>
+        <parameter value="lat_2=34.93333333333333"/>
+        <parameter value="lat_0=34.33333333333334"/>
+        <parameter value="lon_0=-92"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26952" name="NAD83 / Arkansas South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=34.76666666666667"/>
+        <parameter value="lat_2=33.3"/>
+        <parameter value="lat_0=32.66666666666666"/>
+        <parameter value="lon_0=-92"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=400000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26953" name="NAD83 / Colorado North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.78333333333333"/>
+        <parameter value="lat_2=39.71666666666667"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8289"/>
+        <parameter value="y_0=304800.6096"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26954" name="NAD83 / Colorado Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.75"/>
+        <parameter value="lat_2=38.45"/>
+        <parameter value="lat_0=37.83333333333334"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8289"/>
+        <parameter value="y_0=304800.6096"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26955" name="NAD83 / Colorado South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.43333333333333"/>
+        <parameter value="lat_2=37.23333333333333"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-105.5"/>
+        <parameter value="x_0=914401.8289"/>
+        <parameter value="y_0=304800.6096"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26956" name="NAD83 / Connecticut">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.86666666666667"/>
+        <parameter value="lat_2=41.2"/>
+        <parameter value="lat_0=40.83333333333334"/>
+        <parameter value="lon_0=-72.75"/>
+        <parameter value="x_0=304800.6096"/>
+        <parameter value="y_0=152400.3048"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26957" name="NAD83 / Delaware">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=-75.41666666666667"/>
+        <parameter value="k=0.999995"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26958" name="NAD83 / Florida East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.33333333333333"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26959" name="NAD83 / Florida West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.33333333333333"/>
+        <parameter value="lon_0=-82"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26960" name="NAD83 / Florida North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.75"/>
+        <parameter value="lat_2=29.58333333333333"/>
+        <parameter value="lat_0=29"/>
+        <parameter value="lon_0=-84.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26961" name="NAD83 / Hawaii zone 1">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=18.83333333333333"/>
+        <parameter value="lon_0=-155.5"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26962" name="NAD83 / Hawaii zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=20.33333333333333"/>
+        <parameter value="lon_0=-156.6666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26963" name="NAD83 / Hawaii zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=21.16666666666667"/>
+        <parameter value="lon_0=-158"/>
+        <parameter value="k=0.999990"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26964" name="NAD83 / Hawaii zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=21.83333333333333"/>
+        <parameter value="lon_0=-159.5"/>
+        <parameter value="k=0.999990"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26965" name="NAD83 / Hawaii zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=21.66666666666667"/>
+        <parameter value="lon_0=-160.1666666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26966" name="NAD83 / Georgia East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-82.16666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26967" name="NAD83 / Georgia West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=30"/>
+        <parameter value="lon_0=-84.16666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26968" name="NAD83 / Idaho East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-112.1666666666667"/>
+        <parameter value="k=0.999947"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26969" name="NAD83 / Idaho Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-114"/>
+        <parameter value="k=0.999947"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26970" name="NAD83 / Idaho West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-115.75"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26971" name="NAD83 / Illinois East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-88.33333333333333"/>
+        <parameter value="k=0.999975"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26972" name="NAD83 / Illinois West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-90.16666666666667"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26973" name="NAD83 / Indiana East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-85.66666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=100000"/>
+        <parameter value="y_0=250000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26974" name="NAD83 / Indiana West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-87.08333333333333"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=900000"/>
+        <parameter value="y_0=250000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26975" name="NAD83 / Iowa North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=43.26666666666667"/>
+        <parameter value="lat_2=42.06666666666667"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-93.5"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26976" name="NAD83 / Iowa South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.78333333333333"/>
+        <parameter value="lat_2=40.61666666666667"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-93.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26977" name="NAD83 / Kansas North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.78333333333333"/>
+        <parameter value="lat_2=38.71666666666667"/>
+        <parameter value="lat_0=38.33333333333334"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26978" name="NAD83 / Kansas South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.56666666666667"/>
+        <parameter value="lat_2=37.26666666666667"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=400000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26979" name="NAD83 / Kentucky North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.96666666666667"/>
+        <parameter value="lat_2=37.96666666666667"/>
+        <parameter value="lat_0=37.5"/>
+        <parameter value="lon_0=-84.25"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26980" name="NAD83 / Kentucky South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.93333333333333"/>
+        <parameter value="lat_2=36.73333333333333"/>
+        <parameter value="lat_0=36.33333333333334"/>
+        <parameter value="lon_0=-85.75"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26981" name="NAD83 / Louisiana North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=32.66666666666666"/>
+        <parameter value="lat_2=31.16666666666667"/>
+        <parameter value="lat_0=30.5"/>
+        <parameter value="lon_0=-92.5"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26982" name="NAD83 / Louisiana South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.7"/>
+        <parameter value="lat_2=29.3"/>
+        <parameter value="lat_0=28.5"/>
+        <parameter value="lon_0=-91.33333333333333"/>
+        <parameter value="x_0=1000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26983" name="NAD83 / Maine East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=43.66666666666666"/>
+        <parameter value="lon_0=-68.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26984" name="NAD83 / Maine West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=42.83333333333334"/>
+        <parameter value="lon_0=-70.16666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=900000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26985" name="NAD83 / Maryland">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.45"/>
+        <parameter value="lat_2=38.3"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-77"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26986" name="NAD83 / Massachusetts Mainland">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.68333333333333"/>
+        <parameter value="lat_2=41.71666666666667"/>
+        <parameter value="lat_0=41"/>
+        <parameter value="lon_0=-71.5"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=750000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26987" name="NAD83 / Massachusetts Island">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.48333333333333"/>
+        <parameter value="lat_2=41.28333333333333"/>
+        <parameter value="lat_0=41"/>
+        <parameter value="lon_0=-70.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26988" name="NAD83 / Michigan North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.08333333333334"/>
+        <parameter value="lat_2=45.48333333333333"/>
+        <parameter value="lat_0=44.78333333333333"/>
+        <parameter value="lon_0=-87"/>
+        <parameter value="x_0=8000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26989" name="NAD83 / Michigan Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.7"/>
+        <parameter value="lat_2=44.18333333333333"/>
+        <parameter value="lat_0=43.31666666666667"/>
+        <parameter value="lon_0=-84.36666666666666"/>
+        <parameter value="x_0=6000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26990" name="NAD83 / Michigan South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=43.66666666666666"/>
+        <parameter value="lat_2=42.1"/>
+        <parameter value="lat_0=41.5"/>
+        <parameter value="lon_0=-84.36666666666666"/>
+        <parameter value="x_0=4000000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26991" name="NAD83 / Minnesota North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.63333333333333"/>
+        <parameter value="lat_2=47.03333333333333"/>
+        <parameter value="lat_0=46.5"/>
+        <parameter value="lon_0=-93.09999999999999"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26992" name="NAD83 / Minnesota Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.05"/>
+        <parameter value="lat_2=45.61666666666667"/>
+        <parameter value="lat_0=45"/>
+        <parameter value="lon_0=-94.25"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26993" name="NAD83 / Minnesota South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.21666666666667"/>
+        <parameter value="lat_2=43.78333333333333"/>
+        <parameter value="lat_0=43"/>
+        <parameter value="lon_0=-94"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26994" name="NAD83 / Mississippi East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=29.5"/>
+        <parameter value="lon_0=-88.83333333333333"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26995" name="NAD83 / Mississippi West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=29.5"/>
+        <parameter value="lon_0=-90.33333333333333"/>
+        <parameter value="k=0.999950"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26996" name="NAD83 / Missouri East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=35.83333333333334"/>
+        <parameter value="lon_0=-90.5"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=250000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26997" name="NAD83 / Missouri Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=35.83333333333334"/>
+        <parameter value="lon_0=-92.5"/>
+        <parameter value="k=0.999933"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="26998" name="NAD83 / Missouri West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36.16666666666666"/>
+        <parameter value="lon_0=-94.5"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=850000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27038" name="Nahrwan 1967 / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27039" name="Nahrwan 1967 / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27040" name="Nahrwan 1967 / UTM zone 40N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27120" name="Naparima 1972 / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27200" name="NZGD49 / New Zealand Map Grid">
+        <parameter value="proj=nzmg"/>
+        <parameter value="lat_0=-41"/>
+        <parameter value="lon_0=173"/>
+        <parameter value="x_0=2510000"/>
+        <parameter value="y_0=6023150"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27205" name="NZGD49 / Mount Eden Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-36.87986527777778"/>
+        <parameter value="lon_0=174.7643393611111"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27206" name="NZGD49 / Bay of Plenty Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-37.76124980555556"/>
+        <parameter value="lon_0=176.46619725"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27207" name="NZGD49 / Poverty Bay Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-38.62470277777778"/>
+        <parameter value="lon_0=177.8856362777778"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27208" name="NZGD49 / Hawkes Bay Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-39.65092930555556"/>
+        <parameter value="lon_0=176.6736805277778"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27209" name="NZGD49 / Taranaki Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-39.13575830555556"/>
+        <parameter value="lon_0=174.22801175"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27210" name="NZGD49 / Tuhirangi Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-39.51247038888889"/>
+        <parameter value="lon_0=175.6400368055556"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27211" name="NZGD49 / Wanganui Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-40.24194713888889"/>
+        <parameter value="lon_0=175.4880996111111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27212" name="NZGD49 / Wairarapa Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-40.92553263888889"/>
+        <parameter value="lon_0=175.6473496666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27213" name="NZGD49 / Wellington Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-41.30131963888888"/>
+        <parameter value="lon_0=174.7766231111111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27214" name="NZGD49 / Collingwood Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-40.71475905555556"/>
+        <parameter value="lon_0=172.6720465"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27215" name="NZGD49 / Nelson Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-41.27454472222222"/>
+        <parameter value="lon_0=173.2993168055555"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27216" name="NZGD49 / Karamea Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-41.28991152777778"/>
+        <parameter value="lon_0=172.1090281944444"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27217" name="NZGD49 / Buller Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-41.81080286111111"/>
+        <parameter value="lon_0=171.5812600555556"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27218" name="NZGD49 / Grey Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-42.33369427777778"/>
+        <parameter value="lon_0=171.5497713055556"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27219" name="NZGD49 / Amuri Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-42.68911658333333"/>
+        <parameter value="lon_0=173.0101333888889"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27220" name="NZGD49 / Marlborough Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-41.54448666666666"/>
+        <parameter value="lon_0=173.8020741111111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27221" name="NZGD49 / Hokitika Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-42.88632236111111"/>
+        <parameter value="lon_0=170.9799935"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27222" name="NZGD49 / Okarito Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-43.11012813888889"/>
+        <parameter value="lon_0=170.2609258333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27223" name="NZGD49 / Jacksons Bay Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-43.97780288888889"/>
+        <parameter value="lon_0=168.606267"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27224" name="NZGD49 / Mount Pleasant Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-43.59063758333333"/>
+        <parameter value="lon_0=172.7271935833333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27225" name="NZGD49 / Gawler Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-43.74871155555556"/>
+        <parameter value="lon_0=171.3607484722222"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27226" name="NZGD49 / Timaru Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-44.40222036111111"/>
+        <parameter value="lon_0=171.0572508333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27227" name="NZGD49 / Lindis Peak Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-44.73526797222222"/>
+        <parameter value="lon_0=169.4677550833333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27228" name="NZGD49 / Mount Nicholas Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-45.13290258333333"/>
+        <parameter value="lon_0=168.3986411944444"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27229" name="NZGD49 / Mount York Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-45.56372616666666"/>
+        <parameter value="lon_0=167.7388617777778"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27230" name="NZGD49 / Observation Point Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-45.81619661111111"/>
+        <parameter value="lon_0=170.6285951666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27231" name="NZGD49 / North Taieri Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-45.86151336111111"/>
+        <parameter value="lon_0=170.2825891111111"/>
+        <parameter value="k=0.999960"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=700000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27232" name="NZGD49 / Bluff Circuit">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-46.60000961111111"/>
+        <parameter value="lon_0=168.342872"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=300002.66"/>
+        <parameter value="y_0=699999.58"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27258" name="NZGD49 / UTM zone 58S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27259" name="NZGD49 / UTM zone 59S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=59"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27260" name="NZGD49 / UTM zone 60S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=60"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27291" name="NZGD49 / North Island Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-39"/>
+        <parameter value="lon_0=175.5"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=274319.5243848086"/>
+        <parameter value="y_0=365759.3658464114"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="to_meter=0.9143984146160287"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27292" name="NZGD49 / South Island Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=-44"/>
+        <parameter value="lon_0=171.5"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=457199.2073080143"/>
+        <parameter value="y_0=457199.2073080143"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="to_meter=0.9143984146160287"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27391" name="NGO 1948 (Oslo) / NGO zone I">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=58"/>
+        <parameter value="lon_0=6.056250000000003"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="towgs84=278.3,93,474.5,7.889,0.05,-6.61,6.21"/>
+        <parameter value="pm=oslo"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27392" name="NGO 1948 (Oslo) / NGO zone II">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=58"/>
+        <parameter value="lon_0=8.389583333333336"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="towgs84=278.3,93,474.5,7.889,0.05,-6.61,6.21"/>
+        <parameter value="pm=oslo"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27393" name="NGO 1948 (Oslo) / NGO zone III">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=58"/>
+        <parameter value="lon_0=10.72291666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="towgs84=278.3,93,474.5,7.889,0.05,-6.61,6.21"/>
+        <parameter value="pm=oslo"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27394" name="NGO 1948 (Oslo) / NGO zone IV">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=58"/>
+        <parameter value="lon_0=13.22291666666667"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="towgs84=278.3,93,474.5,7.889,0.05,-6.61,6.21"/>
+        <parameter value="pm=oslo"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27395" name="NGO 1948 (Oslo) / NGO zone V">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=58"/>
+        <parameter value="lon_0=16.88958333333334"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="towgs84=278.3,93,474.5,7.889,0.05,-6.61,6.21"/>
+        <parameter value="pm=oslo"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27396" name="NGO 1948 (Oslo) / NGO zone VI">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=58"/>
+        <parameter value="lon_0=20.88958333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="towgs84=278.3,93,474.5,7.889,0.05,-6.61,6.21"/>
+        <parameter value="pm=oslo"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27397" name="NGO 1948 (Oslo) / NGO zone VII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=58"/>
+        <parameter value="lon_0=24.88958333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="towgs84=278.3,93,474.5,7.889,0.05,-6.61,6.21"/>
+        <parameter value="pm=oslo"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27398" name="NGO 1948 (Oslo) / NGO zone VIII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=58"/>
+        <parameter value="lon_0=29.05625"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="a=6377492.018"/>
+        <parameter value="b=6356173.508712696"/>
+        <parameter value="towgs84=278.3,93,474.5,7.889,0.05,-6.61,6.21"/>
+        <parameter value="pm=oslo"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27429" name="Datum 73 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27492" name="Datum 73 / Modified Portuguese Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=39.66666666666666"/>
+        <parameter value="lon_0=-8.131906111111112"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=180.598"/>
+        <parameter value="y_0=-86.98999999999999"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27500" name="ATF (Paris) / Nord de Guerre">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49.50000000000001"/>
+        <parameter value="lat_0=49.50000000000001"/>
+        <parameter value="lon_0=7.737229170000001"/>
+        <parameter value="k_0=0.99950908"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="a=6376523"/>
+        <parameter value="b=6355862.933255573"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27561" name="NTF (Paris) / Lambert Nord France">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49.50000000000001"/>
+        <parameter value="lat_0=49.50000000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.999877341"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27562" name="NTF (Paris) / Lambert Centre France">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.8"/>
+        <parameter value="lat_0=46.8"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.99987742"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27563" name="NTF (Paris) / Lambert Sud France">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.10000000000001"/>
+        <parameter value="lat_0=44.10000000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.999877499"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27564" name="NTF (Paris) / Lambert Corse">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.16500000000001"/>
+        <parameter value="lat_0=42.16500000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.99994471"/>
+        <parameter value="x_0=234.358"/>
+        <parameter value="y_0=185861.369"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27571" name="NTF (Paris) / Lambert zone I">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49.50000000000001"/>
+        <parameter value="lat_0=49.50000000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.999877341"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=1200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27572" name="NTF (Paris) / Lambert zone II">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.8"/>
+        <parameter value="lat_0=46.8"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.99987742"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=2200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27573" name="NTF (Paris) / Lambert zone III">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.10000000000001"/>
+        <parameter value="lat_0=44.10000000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.999877499"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=3200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27574" name="NTF (Paris) / Lambert zone IV">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.16500000000001"/>
+        <parameter value="lat_0=42.16500000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.99994471"/>
+        <parameter value="x_0=234.358"/>
+        <parameter value="y_0=4185861.369"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27581" name="NTF (Paris) / France I">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49.50000000000001"/>
+        <parameter value="lat_0=49.50000000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.999877341"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=1200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27582" name="NTF (Paris) / France II">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.8"/>
+        <parameter value="lat_0=46.8"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.99987742"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=2200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27583" name="NTF (Paris) / France III">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.10000000000001"/>
+        <parameter value="lat_0=44.10000000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.999877499"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=3200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27584" name="NTF (Paris) / France IV">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.16500000000001"/>
+        <parameter value="lat_0=42.16500000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.99994471"/>
+        <parameter value="x_0=234.358"/>
+        <parameter value="y_0=4185861.369"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27591" name="NTF (Paris) / Nord France">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49.50000000000001"/>
+        <parameter value="lat_0=49.50000000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.999877341"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27592" name="NTF (Paris) / Centre France">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.8"/>
+        <parameter value="lat_0=46.8"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.99987742"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27593" name="NTF (Paris) / Sud France">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.10000000000001"/>
+        <parameter value="lat_0=44.10000000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.999877499"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=200000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27594" name="NTF (Paris) / Corse">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.16500000000001"/>
+        <parameter value="lat_0=42.16500000000001"/>
+        <parameter value="lon_0=2.33722917"/>
+        <parameter value="k_0=0.99994471"/>
+        <parameter value="x_0=234.358"/>
+        <parameter value="y_0=185861.369"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-168,-60,320,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="27700" name="OSGB 1936 / British National Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=49"/>
+        <parameter value="lon_0=-2"/>
+        <parameter value="k=0.999601"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=-100000"/>
+        <parameter value="ellps=airy"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28191" name="Palestine 1923 / Palestine Grid">
+        <parameter value="proj=cass"/>
+        <parameter value="lat_0=31.73409694444445"/>
+        <parameter value="lon_0=35.21208055555556"/>
+        <parameter value="x_0=170251.555"/>
+        <parameter value="y_0=126867.909"/>
+        <parameter value="a=6378300.789"/>
+        <parameter value="b=6356566.435"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28192" name="Palestine 1923 / Palestine Belt">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31.73409694444445"/>
+        <parameter value="lon_0=35.21208055555556"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=170251.555"/>
+        <parameter value="y_0=1126867.909"/>
+        <parameter value="a=6378300.789"/>
+        <parameter value="b=6356566.435"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28193" name="Palestine 1923 / Israeli CS Grid">
+        <parameter value="proj=cass"/>
+        <parameter value="lat_0=31.73409694444445"/>
+        <parameter value="lon_0=35.21208055555556"/>
+        <parameter value="x_0=170251.555"/>
+        <parameter value="y_0=1126867.909"/>
+        <parameter value="a=6378300.789"/>
+        <parameter value="b=6356566.435"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28232" name="Pointe Noire / UTM zone 32S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="south"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28348" name="GDA94 / MGA zone 48">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28349" name="GDA94 / MGA zone 49">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28350" name="GDA94 / MGA zone 50">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28351" name="GDA94 / MGA zone 51">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28352" name="GDA94 / MGA zone 52">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28353" name="GDA94 / MGA zone 53">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28354" name="GDA94 / MGA zone 54">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=54"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28355" name="GDA94 / MGA zone 55">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=55"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28356" name="GDA94 / MGA zone 56">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=56"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28357" name="GDA94 / MGA zone 57">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=57"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28358" name="GDA94 / MGA zone 58">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28402" name="Pulkovo 1942 / Gauss-Kruger zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=9"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28403" name="Pulkovo 1942 / Gauss-Kruger zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28404" name="Pulkovo 1942 / Gauss-Kruger zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28405" name="Pulkovo 1942 / Gauss-Kruger zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28406" name="Pulkovo 1942 / Gauss-Kruger zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=6500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28407" name="Pulkovo 1942 / Gauss-Kruger zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=7500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28408" name="Pulkovo 1942 / Gauss-Kruger zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=8500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28409" name="Pulkovo 1942 / Gauss-Kruger zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=9500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28410" name="Pulkovo 1942 / Gauss-Kruger zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=10500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28411" name="Pulkovo 1942 / Gauss-Kruger zone 11">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=11500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28412" name="Pulkovo 1942 / Gauss-Kruger zone 12">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=12500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28413" name="Pulkovo 1942 / Gauss-Kruger zone 13">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=13500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28414" name="Pulkovo 1942 / Gauss-Kruger zone 14">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=14500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28415" name="Pulkovo 1942 / Gauss-Kruger zone 15">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=15500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28416" name="Pulkovo 1942 / Gauss-Kruger zone 16">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=16500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28417" name="Pulkovo 1942 / Gauss-Kruger zone 17">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=17500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28418" name="Pulkovo 1942 / Gauss-Kruger zone 18">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=18500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28419" name="Pulkovo 1942 / Gauss-Kruger zone 19">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=19500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28420" name="Pulkovo 1942 / Gauss-Kruger zone 20">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=20500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28421" name="Pulkovo 1942 / Gauss-Kruger zone 21">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=21500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28422" name="Pulkovo 1942 / Gauss-Kruger zone 22">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=22500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28423" name="Pulkovo 1942 / Gauss-Kruger zone 23">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=23500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28424" name="Pulkovo 1942 / Gauss-Kruger zone 24">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=141"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=24500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28425" name="Pulkovo 1942 / Gauss-Kruger zone 25">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=147"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=25500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28426" name="Pulkovo 1942 / Gauss-Kruger zone 26">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=153"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=26500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28427" name="Pulkovo 1942 / Gauss-Kruger zone 27">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=159"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=27500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28428" name="Pulkovo 1942 / Gauss-Kruger zone 28">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=165"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=28500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28429" name="Pulkovo 1942 / Gauss-Kruger zone 29">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=29500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28430" name="Pulkovo 1942 / Gauss-Kruger zone 30">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=30500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28431" name="Pulkovo 1942 / Gauss-Kruger zone 31">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=31500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28432" name="Pulkovo 1942 / Gauss-Kruger zone 32">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=32500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28462" name="Pulkovo 1942 / Gauss-Kruger 2N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=9"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28463" name="Pulkovo 1942 / Gauss-Kruger 3N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28464" name="Pulkovo 1942 / Gauss-Kruger 4N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28465" name="Pulkovo 1942 / Gauss-Kruger 5N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=27"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28466" name="Pulkovo 1942 / Gauss-Kruger 6N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=33"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28467" name="Pulkovo 1942 / Gauss-Kruger 7N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=39"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28468" name="Pulkovo 1942 / Gauss-Kruger 8N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=45"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28469" name="Pulkovo 1942 / Gauss-Kruger 9N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=51"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28470" name="Pulkovo 1942 / Gauss-Kruger 10N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=57"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28471" name="Pulkovo 1942 / Gauss-Kruger 11N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=63"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28472" name="Pulkovo 1942 / Gauss-Kruger 12N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=69"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28473" name="Pulkovo 1942 / Gauss-Kruger 13N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=75"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28474" name="Pulkovo 1942 / Gauss-Kruger 14N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=81"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28475" name="Pulkovo 1942 / Gauss-Kruger 15N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=87"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28476" name="Pulkovo 1942 / Gauss-Kruger 16N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=93"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28477" name="Pulkovo 1942 / Gauss-Kruger 17N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=99"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28478" name="Pulkovo 1942 / Gauss-Kruger 18N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=105"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28479" name="Pulkovo 1942 / Gauss-Kruger 19N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=111"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28480" name="Pulkovo 1942 / Gauss-Kruger 20N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=117"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28481" name="Pulkovo 1942 / Gauss-Kruger 21N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=123"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28482" name="Pulkovo 1942 / Gauss-Kruger 22N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=129"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28483" name="Pulkovo 1942 / Gauss-Kruger 23N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=135"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28484" name="Pulkovo 1942 / Gauss-Kruger 24N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=141"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28485" name="Pulkovo 1942 / Gauss-Kruger 25N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=147"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28486" name="Pulkovo 1942 / Gauss-Kruger 26N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=153"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28487" name="Pulkovo 1942 / Gauss-Kruger 27N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=159"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28488" name="Pulkovo 1942 / Gauss-Kruger 28N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=165"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28489" name="Pulkovo 1942 / Gauss-Kruger 29N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28490" name="Pulkovo 1942 / Gauss-Kruger 30N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28491" name="Pulkovo 1942 / Gauss-Kruger 31N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-177"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28492" name="Pulkovo 1942 / Gauss-Kruger 32N">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-171"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28600" name="Qatar 1974 / Qatar National Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=24.45"/>
+        <parameter value="lon_0=51.21666666666667"/>
+        <parameter value="k=0.999990"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28991" name="Amersfoort / RD Old">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=52.15616055555555"/>
+        <parameter value="lon_0=5.38763888888889"/>
+        <parameter value="k=0.999908"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="28992" name="Amersfoort / RD New">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=52.15616055555555"/>
+        <parameter value="lon_0=5.38763888888889"/>
+        <parameter value="k=0.999908"/>
+        <parameter value="x_0=155000"/>
+        <parameter value="y_0=463000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29100" name="SAD69 / Brazil Polyconic">
+        <parameter value="proj=poly"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-54"/>
+        <parameter value="x_0=5000000"/>
+        <parameter value="y_0=10000000"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29118" name="SAD69 / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29119" name="SAD69 / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29120" name="SAD69 / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29121" name="SAD69 / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29122" name="SAD69 / UTM zone 22N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29177" name="SAD69 / UTM zone 17S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29178" name="SAD69 / UTM zone 18S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29179" name="SAD69 / UTM zone 19S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29180" name="SAD69 / UTM zone 20S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29181" name="SAD69 / UTM zone 21S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29182" name="SAD69 / UTM zone 22S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29183" name="SAD69 / UTM zone 23S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29184" name="SAD69 / UTM zone 24S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=24"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29185" name="SAD69 / UTM zone 25S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=25"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS67"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29220" name="Sapper Hill 1943 / UTM zone 20S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-355,21,72,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29221" name="Sapper Hill 1943 / UTM zone 21S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-355,21,72,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29333" name="Schwarzeck / UTM zone 33S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="south"/>
+        <parameter value="ellps=bess_nam"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29635" name="Sudan / UTM zone 35N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29636" name="Sudan / UTM zone 36N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29700" name="Tananarive (Paris) / Laborde Grid">
+        <parameter value="proj=omerc"/>
+        <parameter value="lat_0=-18.9"/>
+        <parameter value="lonc=46.43722917000001"/>
+        <parameter value="alpha=18.9"/>
+        <parameter value="k=0.9995000000000001"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=800000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-189,-242,-91,0,0,0,0"/>
+        <parameter value="pm=paris"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29738" name="Tananarive / UTM zone 38S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-189,-242,-91,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29739" name="Tananarive / UTM zone 39S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="south"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-189,-242,-91,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29849" name="Timbalai 1948 / UTM zone 49N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="ellps=evrstSS"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29850" name="Timbalai 1948 / UTM zone 50N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="ellps=evrstSS"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29871" name="Timbalai 1948 / R.S.O. Borneo (ch)">
+        <parameter value="proj=omerc"/>
+        <parameter value="lat_0=4"/>
+        <parameter value="lonc=115"/>
+        <parameter value="alpha=53.31582047222222"/>
+        <parameter value="k=0.99984"/>
+        <parameter value="x_0=590476.8714630401"/>
+        <parameter value="y_0=442857.653094361"/>
+        <parameter value="ellps=evrstSS"/>
+        <parameter value="to_meter=20.11676512155263"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29872" name="Timbalai 1948 / R.S.O. Borneo (ft)">
+        <parameter value="proj=omerc"/>
+        <parameter value="lat_0=4"/>
+        <parameter value="lonc=115"/>
+        <parameter value="alpha=53.31582047222222"/>
+        <parameter value="k=0.99984"/>
+        <parameter value="x_0=590476.8727431979"/>
+        <parameter value="y_0=442857.6545573985"/>
+        <parameter value="ellps=evrstSS"/>
+        <parameter value="to_meter=0.3047994715386762"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29873" name="Timbalai 1948 / R.S.O. Borneo (m)">
+        <parameter value="proj=omerc"/>
+        <parameter value="lat_0=4"/>
+        <parameter value="lonc=115"/>
+        <parameter value="alpha=53.31582047222222"/>
+        <parameter value="k=0.99984"/>
+        <parameter value="x_0=590476.87"/>
+        <parameter value="y_0=442857.65"/>
+        <parameter value="ellps=evrstSS"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29900" name="TM65 / Irish National Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=53.5"/>
+        <parameter value="lon_0=-8"/>
+        <parameter value="k=1.000035"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=250000"/>
+        <parameter value="a=6377340.189"/>
+        <parameter value="b=6356034.447938534"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29901" name="OSNI 1952 / Irish National Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=53.5"/>
+        <parameter value="lon_0=-8"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=250000"/>
+        <parameter value="ellps=airy"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29902" name="TM65 / Irish Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=53.5"/>
+        <parameter value="lon_0=-8"/>
+        <parameter value="k=1.000035"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=250000"/>
+        <parameter value="a=6377340.189"/>
+        <parameter value="b=6356034.447938534"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="29903" name="TM75 / Irish Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=53.5"/>
+        <parameter value="lon_0=-8"/>
+        <parameter value="k=1.000035"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=250000"/>
+        <parameter value="a=6377340.189"/>
+        <parameter value="b=6356034.447938534"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30161" name="Tokyo / Japan Plane Rectangular CS I">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=33"/>
+        <parameter value="lon_0=129.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30162" name="Tokyo / Japan Plane Rectangular CS II">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=33"/>
+        <parameter value="lon_0=131"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30163" name="Tokyo / Japan Plane Rectangular CS III">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=132.1666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30164" name="Tokyo / Japan Plane Rectangular CS IV">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=33"/>
+        <parameter value="lon_0=133.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30165" name="Tokyo / Japan Plane Rectangular CS V">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=134.3333333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30166" name="Tokyo / Japan Plane Rectangular CS VI">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=136"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30167" name="Tokyo / Japan Plane Rectangular CS VII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=137.1666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30168" name="Tokyo / Japan Plane Rectangular CS VIII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=138.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30169" name="Tokyo / Japan Plane Rectangular CS IX">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=139.8333333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30170" name="Tokyo / Japan Plane Rectangular CS X">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=140.8333333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30171" name="Tokyo / Japan Plane Rectangular CS XI">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=44"/>
+        <parameter value="lon_0=140.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30172" name="Tokyo / Japan Plane Rectangular CS XII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=44"/>
+        <parameter value="lon_0=142.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30173" name="Tokyo / Japan Plane Rectangular CS XIII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=44"/>
+        <parameter value="lon_0=144.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30174" name="Tokyo / Japan Plane Rectangular CS XIV">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=142"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30175" name="Tokyo / Japan Plane Rectangular CS XV">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=127.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30176" name="Tokyo / Japan Plane Rectangular CS XVI">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=124"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30177" name="Tokyo / Japan Plane Rectangular CS XVII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=131"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30178" name="Tokyo / Japan Plane Rectangular CS XVIII">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=20"/>
+        <parameter value="lon_0=136"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30179" name="Tokyo / Japan Plane Rectangular CS XIX">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=26"/>
+        <parameter value="lon_0=154"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30200" name="Trinidad 1903 / Trinidad Grid">
+        <parameter value="proj=cass"/>
+        <parameter value="lat_0=10.44166666666667"/>
+        <parameter value="lon_0=-61.33333333333334"/>
+        <parameter value="x_0=86501.46380700001"/>
+        <parameter value="y_0=65379.0133425"/>
+        <parameter value="a=6378293.63683822"/>
+        <parameter value="b=6356617.979337744"/>
+        <parameter value="towgs84=-61.702,284.488,472.052,0,0,0,0"/>
+        <parameter value="to_meter=0.2011661949"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30339" name="TC(1948) / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30340" name="TC(1948) / UTM zone 40N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="ellps=helmert"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30491" name="Voirol 1875 / Nord Algerie (ancienne)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=2.7"/>
+        <parameter value="k_0=0.999625544"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-73,-247,227,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30492" name="Voirol 1875 / Sud Algerie (ancienne)">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.3"/>
+        <parameter value="lat_0=33.3"/>
+        <parameter value="lon_0=2.7"/>
+        <parameter value="k_0=0.999625769"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=300000"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-73,-247,227,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30729" name="Nord Sahara 1959 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30730" name="Nord Sahara 1959 / UTM zone 30N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30731" name="Nord Sahara 1959 / UTM zone 31N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30732" name="Nord Sahara 1959 / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30791" name="Nord Sahara 1959 / Voirol Unifie Nord">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36"/>
+        <parameter value="lat_0=36"/>
+        <parameter value="lon_0=2.7"/>
+        <parameter value="k_0=0.999625544"/>
+        <parameter value="x_0=500135"/>
+        <parameter value="y_0=300090"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30792" name="Nord Sahara 1959 / Voirol Unifie Sud">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.3"/>
+        <parameter value="lat_0=33.3"/>
+        <parameter value="lon_0=2.7"/>
+        <parameter value="k_0=0.999625769"/>
+        <parameter value="x_0=500135"/>
+        <parameter value="y_0=300090"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="30800" name="RT38 2.5 gon W">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15.80827777777778"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31028" name="Yoff / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31121" name="Zanderij / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-265,120,-358,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31154" name="Zanderij / TM 54 NW">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-54"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-265,120,-358,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31170" name="Zanderij / Suriname Old TM">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-55.68333333333333"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-265,120,-358,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31171" name="Zanderij / Suriname TM">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-55.68333333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=-265,120,-358,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31265" name="MGI / 3-degree Gauss zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31266" name="MGI / 3-degree Gauss zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=18"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=6500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31267" name="MGI / 3-degree Gauss zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=7500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31268" name="MGI / 3-degree Gauss zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=8500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31275" name="MGI / Balkans zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31276" name="MGI / Balkans zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=18"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=6500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31277" name="MGI / Balkans zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=7500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31278" name="MGI / Balkans zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=21"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=7500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31279" name="MGI / Balkans zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=24"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=8500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31281" name="MGI (Ferro) / Austria West Zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=10.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=ferro"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31282" name="MGI (Ferro) / Austria Central Zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=13.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=ferro"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31283" name="MGI (Ferro) / Austria East Zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=16.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=ferro"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31284" name="MGI / M28">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=10.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=150000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31285" name="MGI / M31">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=13.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=450000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31286" name="MGI / M34">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=16.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=750000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31287" name="MGI / Austria Lambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49"/>
+        <parameter value="lat_2=46"/>
+        <parameter value="lat_0=47.5"/>
+        <parameter value="lon_0=13.33333333333333"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=400000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31291" name="MGI (Ferro) / Austria West Zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=10.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=ferro"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31292" name="MGI (Ferro) / Austria Central Zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=13.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=ferro"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31293" name="MGI (Ferro) / Austria East Zone">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=16.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="pm=ferro"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31294" name="MGI / M28">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=10.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=150000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31295" name="MGI / M31">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=13.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=450000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31296" name="MGI / M34">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=16.33333333333333"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=750000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31297" name="MGI / Austria Lambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49"/>
+        <parameter value="lat_2=46"/>
+        <parameter value="lat_0=47.5"/>
+        <parameter value="lon_0=13.33333333333333"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=400000"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31300" name="Belge 1972 / Belge Lambert 72">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49.83333333333334"/>
+        <parameter value="lat_2=51.16666666666666"/>
+        <parameter value="lat_0=90"/>
+        <parameter value="lon_0=4.356939722222222"/>
+        <parameter value="x_0=150000.01256"/>
+        <parameter value="y_0=5400088.4378"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31370" name="Belge 1972 / Belgian Lambert 72">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=51.16666723333333"/>
+        <parameter value="lat_2=49.8333339"/>
+        <parameter value="lat_0=90"/>
+        <parameter value="lon_0=4.367486666666666"/>
+        <parameter value="x_0=150000.013"/>
+        <parameter value="y_0=5400088.438"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31461" name="DHDN / 3-degree Gauss zone 1">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=3"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31462" name="DHDN / 3-degree Gauss zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=6"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31463" name="DHDN / 3-degree Gauss zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=9"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31464" name="DHDN / 3-degree Gauss zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=12"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31465" name="DHDN / 3-degree Gauss zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31466" name="DHDN / Gauss-Kruger zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=6"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31467" name="DHDN / Gauss-Kruger zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=9"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31468" name="DHDN / Gauss-Kruger zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=12"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=4500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31469" name="DHDN / Gauss-Kruger zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=15"/>
+        <parameter value="k=1.000000"/>
+        <parameter value="x_0=5500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=bessel"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31528" name="Conakry 1905 / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-23,259,-9,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31529" name="Conakry 1905 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="a=6378249.2"/>
+        <parameter value="b=6356515"/>
+        <parameter value="towgs84=-23,259,-9,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31600" name="Dealul Piscului 1933/ Stereo 33">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=45.9"/>
+        <parameter value="lon_0=25.39246588888889"/>
+        <parameter value="k=0.999667"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=intl"/>
+        <parameter value="towgs84=103.25,-100.4,-307.19,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31700" name="Dealul Piscului 1970/ Stereo 70">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=46"/>
+        <parameter value="lon_0=25"/>
+        <parameter value="k=0.999750"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=500000"/>
+        <parameter value="ellps=krass"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31838" name="NGN / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31839" name="NGN / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31900" name="KUDAMS / KTM">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=48"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31986" name="SIRGAS / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31987" name="SIRGAS / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31988" name="SIRGAS / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31989" name="SIRGAS / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31990" name="SIRGAS / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31991" name="SIRGAS / UTM zone 22N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31992" name="SIRGAS / UTM zone 17S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31993" name="SIRGAS / UTM zone 18S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31994" name="SIRGAS / UTM zone 19S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31995" name="SIRGAS / UTM zone 20S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31996" name="SIRGAS / UTM zone 21S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31997" name="SIRGAS / UTM zone 22S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31998" name="SIRGAS / UTM zone 23S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="31999" name="SIRGAS / UTM zone 24S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=24"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32000" name="SIRGAS / UTM zone 25S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=25"/>
+        <parameter value="south"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="towgs84=0,0,0,0,0,0,0"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32001" name="NAD27 / Montana North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.71666666666667"/>
+        <parameter value="lat_2=47.85"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-109.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32002" name="NAD27 / Montana Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.88333333333333"/>
+        <parameter value="lat_2=46.45"/>
+        <parameter value="lat_0=45.83333333333334"/>
+        <parameter value="lon_0=-109.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32003" name="NAD27 / Montana South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.4"/>
+        <parameter value="lat_2=44.86666666666667"/>
+        <parameter value="lat_0=44"/>
+        <parameter value="lon_0=-109.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32005" name="NAD27 / Nebraska North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.85"/>
+        <parameter value="lat_2=42.81666666666667"/>
+        <parameter value="lat_0=41.33333333333334"/>
+        <parameter value="lon_0=-100"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32006" name="NAD27 / Nebraska South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.28333333333333"/>
+        <parameter value="lat_2=41.71666666666667"/>
+        <parameter value="lat_0=39.66666666666666"/>
+        <parameter value="lon_0=-99.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32007" name="NAD27 / Nevada East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=34.75"/>
+        <parameter value="lon_0=-115.5833333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32008" name="NAD27 / Nevada Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=34.75"/>
+        <parameter value="lon_0=-116.6666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32009" name="NAD27 / Nevada West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=34.75"/>
+        <parameter value="lon_0=-118.5833333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32010" name="NAD27 / New Hampshire">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=42.5"/>
+        <parameter value="lon_0=-71.66666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32011" name="NAD27 / New Jersey">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38.83333333333334"/>
+        <parameter value="lon_0=-74.66666666666667"/>
+        <parameter value="k=0.999975"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32012" name="NAD27 / New Mexico East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-104.3333333333333"/>
+        <parameter value="k=0.999909"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32013" name="NAD27 / New Mexico Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-106.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32014" name="NAD27 / New Mexico West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-107.8333333333333"/>
+        <parameter value="k=0.999917"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32015" name="NAD27 / New York East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-74.33333333333333"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32016" name="NAD27 / New York Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-76.58333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32017" name="NAD27 / New York West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-78.58333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32018" name="NAD27 / New York Long Island">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.03333333333333"/>
+        <parameter value="lat_2=40.66666666666666"/>
+        <parameter value="lat_0=40.5"/>
+        <parameter value="lon_0=-74"/>
+        <parameter value="x_0=304800.6096012192"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32019" name="NAD27 / North Carolina">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=34.33333333333334"/>
+        <parameter value="lat_2=36.16666666666666"/>
+        <parameter value="lat_0=33.75"/>
+        <parameter value="lon_0=-79"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32020" name="NAD27 / North Dakota North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.43333333333333"/>
+        <parameter value="lat_2=48.73333333333333"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-100.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32021" name="NAD27 / North Dakota South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.18333333333333"/>
+        <parameter value="lat_2=47.48333333333333"/>
+        <parameter value="lat_0=45.66666666666666"/>
+        <parameter value="lon_0=-100.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32022" name="NAD27 / Ohio North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.43333333333333"/>
+        <parameter value="lat_2=41.7"/>
+        <parameter value="lat_0=39.66666666666666"/>
+        <parameter value="lon_0=-82.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32023" name="NAD27 / Ohio South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.73333333333333"/>
+        <parameter value="lat_2=40.03333333333333"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=-82.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32024" name="NAD27 / Oklahoma North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.56666666666667"/>
+        <parameter value="lat_2=36.76666666666667"/>
+        <parameter value="lat_0=35"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32025" name="NAD27 / Oklahoma South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.93333333333333"/>
+        <parameter value="lat_2=35.23333333333333"/>
+        <parameter value="lat_0=33.33333333333334"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32026" name="NAD27 / Oregon North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.33333333333334"/>
+        <parameter value="lat_2=46"/>
+        <parameter value="lat_0=43.66666666666666"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32027" name="NAD27 / Oregon South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.33333333333334"/>
+        <parameter value="lat_2=44"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32028" name="NAD27 / Pennsylvania North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.88333333333333"/>
+        <parameter value="lat_2=41.95"/>
+        <parameter value="lat_0=40.16666666666666"/>
+        <parameter value="lon_0=-77.75"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32029" name="NAD27 / Pennsylvania South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.93333333333333"/>
+        <parameter value="lat_2=40.8"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-77.75"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32030" name="NAD27 / Rhode Island">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.08333333333334"/>
+        <parameter value="lon_0=-71.5"/>
+        <parameter value="k=0.999994"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32031" name="NAD27 / South Carolina North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.76666666666667"/>
+        <parameter value="lat_2=34.96666666666667"/>
+        <parameter value="lat_0=33"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32033" name="NAD27 / South Carolina South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=32.33333333333334"/>
+        <parameter value="lat_2=33.66666666666666"/>
+        <parameter value="lat_0=31.83333333333333"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32034" name="NAD27 / South Dakota North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.41666666666666"/>
+        <parameter value="lat_2=45.68333333333333"/>
+        <parameter value="lat_0=43.83333333333334"/>
+        <parameter value="lon_0=-100"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32035" name="NAD27 / South Dakota South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.83333333333334"/>
+        <parameter value="lat_2=44.4"/>
+        <parameter value="lat_0=42.33333333333334"/>
+        <parameter value="lon_0=-100.3333333333333"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32036" name="NAD27 / Tennessee">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.25"/>
+        <parameter value="lat_2=36.41666666666666"/>
+        <parameter value="lat_0=34.66666666666666"/>
+        <parameter value="lon_0=-86"/>
+        <parameter value="x_0=30480.06096012192"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32037" name="NAD27 / Texas North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=34.65"/>
+        <parameter value="lat_2=36.18333333333333"/>
+        <parameter value="lat_0=34"/>
+        <parameter value="lon_0=-101.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32038" name="NAD27 / Texas North Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=32.13333333333333"/>
+        <parameter value="lat_2=33.96666666666667"/>
+        <parameter value="lat_0=31.66666666666667"/>
+        <parameter value="lon_0=-97.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32039" name="NAD27 / Texas Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.11666666666667"/>
+        <parameter value="lat_2=31.88333333333333"/>
+        <parameter value="lat_0=29.66666666666667"/>
+        <parameter value="lon_0=-100.3333333333333"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32040" name="NAD27 / Texas South Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=28.38333333333333"/>
+        <parameter value="lat_2=30.28333333333333"/>
+        <parameter value="lat_0=27.83333333333333"/>
+        <parameter value="lon_0=-99"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32041" name="NAD27 / Texas South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=26.16666666666667"/>
+        <parameter value="lat_2=27.83333333333333"/>
+        <parameter value="lat_0=25.66666666666667"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32042" name="NAD27 / Utah North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.71666666666667"/>
+        <parameter value="lat_2=41.78333333333333"/>
+        <parameter value="lat_0=40.33333333333334"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32043" name="NAD27 / Utah Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.01666666666667"/>
+        <parameter value="lat_2=40.65"/>
+        <parameter value="lat_0=38.33333333333334"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32044" name="NAD27 / Utah South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.21666666666667"/>
+        <parameter value="lat_2=38.35"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32045" name="NAD27 / Vermont">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=42.5"/>
+        <parameter value="lon_0=-72.5"/>
+        <parameter value="k=0.999964"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32046" name="NAD27 / Virginia North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.03333333333333"/>
+        <parameter value="lat_2=39.2"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-78.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32047" name="NAD27 / Virginia South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.76666666666667"/>
+        <parameter value="lat_2=37.96666666666667"/>
+        <parameter value="lat_0=36.33333333333334"/>
+        <parameter value="lon_0=-78.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32048" name="NAD27 / Washington North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.5"/>
+        <parameter value="lat_2=48.73333333333333"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-120.8333333333333"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32049" name="NAD27 / Washington South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.83333333333334"/>
+        <parameter value="lat_2=47.33333333333334"/>
+        <parameter value="lat_0=45.33333333333334"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32050" name="NAD27 / West Virginia North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39"/>
+        <parameter value="lat_2=40.25"/>
+        <parameter value="lat_0=38.5"/>
+        <parameter value="lon_0=-79.5"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32051" name="NAD27 / West Virginia South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.48333333333333"/>
+        <parameter value="lat_2=38.88333333333333"/>
+        <parameter value="lat_0=37"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32052" name="NAD27 / Wisconsin North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.56666666666667"/>
+        <parameter value="lat_2=46.76666666666667"/>
+        <parameter value="lat_0=45.16666666666666"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32053" name="NAD27 / Wisconsin Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.25"/>
+        <parameter value="lat_2=45.5"/>
+        <parameter value="lat_0=43.83333333333334"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32054" name="NAD27 / Wisconsin South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=42.73333333333333"/>
+        <parameter value="lat_2=44.06666666666667"/>
+        <parameter value="lat_0=42"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=609601.2192024384"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32055" name="NAD27 / Wyoming East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.66666666666666"/>
+        <parameter value="lon_0=-105.1666666666667"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32056" name="NAD27 / Wyoming East Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.66666666666666"/>
+        <parameter value="lon_0=-107.3333333333333"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32057" name="NAD27 / Wyoming West Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.66666666666666"/>
+        <parameter value="lon_0=-108.75"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32058" name="NAD27 / Wyoming West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.66666666666666"/>
+        <parameter value="lon_0=-110.0833333333333"/>
+        <parameter value="k=0.999941"/>
+        <parameter value="x_0=152400.3048006096"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32061" name="NAD27 / Guatemala Norte">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=16.81666666666667"/>
+        <parameter value="lat_0=16.81666666666667"/>
+        <parameter value="lon_0=-90.33333333333333"/>
+        <parameter value="k_0=0.99992226"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=292209.579"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32062" name="NAD27 / Guatemala Sur">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=14.9"/>
+        <parameter value="lat_0=14.9"/>
+        <parameter value="lon_0=-90.33333333333333"/>
+        <parameter value="k_0=0.99989906"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=325992.681"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32064" name="NAD27 / BLM 14N (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-99"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000.001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32065" name="NAD27 / BLM 15N (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-93"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000.001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32066" name="NAD27 / BLM 16N (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-87"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000.001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32067" name="NAD27 / BLM 17N (ftUS)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000.001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32074" name="NAD27 / BLM 14N (feet)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-99"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000.001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32075" name="NAD27 / BLM 15N (feet)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-93"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000.001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32076" name="NAD27 / BLM 16N (feet)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-87"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000.001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32077" name="NAD27 / BLM 17N (feet)">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000.001016002"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="to_meter=0.3048006096012192"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32081" name="NAD27 / MTM zone 1">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-53"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32082" name="NAD27 / MTM zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-56"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32083" name="NAD27 / MTM zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-58.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32084" name="NAD27 / MTM zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-61.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32085" name="NAD27 / MTM zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-64.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32086" name="NAD27 / MTM zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-67.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32098" name="NAD27 / Quebec Lambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=60"/>
+        <parameter value="lat_2=46"/>
+        <parameter value="lat_0=44"/>
+        <parameter value="lon_0=-68.5"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="datum=NAD27"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32100" name="NAD83 / Montana">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=49"/>
+        <parameter value="lat_2=45"/>
+        <parameter value="lat_0=44.25"/>
+        <parameter value="lon_0=-109.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32104" name="NAD83 / Nebraska">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=43"/>
+        <parameter value="lat_2=40"/>
+        <parameter value="lat_0=39.83333333333334"/>
+        <parameter value="lon_0=-100"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32107" name="NAD83 / Nevada East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=34.75"/>
+        <parameter value="lon_0=-115.5833333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=8000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32108" name="NAD83 / Nevada Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=34.75"/>
+        <parameter value="lon_0=-116.6666666666667"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=6000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32109" name="NAD83 / Nevada West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=34.75"/>
+        <parameter value="lon_0=-118.5833333333333"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=4000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32110" name="NAD83 / New Hampshire">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=42.5"/>
+        <parameter value="lon_0=-71.66666666666667"/>
+        <parameter value="k=0.999967"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32111" name="NAD83 / New Jersey">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38.83333333333334"/>
+        <parameter value="lon_0=-74.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=150000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32112" name="NAD83 / New Mexico East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-104.3333333333333"/>
+        <parameter value="k=0.999909"/>
+        <parameter value="x_0=165000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32113" name="NAD83 / New Mexico Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-106.25"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32114" name="NAD83 / New Mexico West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=31"/>
+        <parameter value="lon_0=-107.8333333333333"/>
+        <parameter value="k=0.999917"/>
+        <parameter value="x_0=830000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32115" name="NAD83 / New York East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=38.83333333333334"/>
+        <parameter value="lon_0=-74.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=150000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32116" name="NAD83 / New York Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-76.58333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=250000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32117" name="NAD83 / New York West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40"/>
+        <parameter value="lon_0=-78.58333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=350000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32118" name="NAD83 / New York Long Island">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.03333333333333"/>
+        <parameter value="lat_2=40.66666666666666"/>
+        <parameter value="lat_0=40.16666666666666"/>
+        <parameter value="lon_0=-74"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32119" name="NAD83 / North Carolina">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.16666666666666"/>
+        <parameter value="lat_2=34.33333333333334"/>
+        <parameter value="lat_0=33.75"/>
+        <parameter value="lon_0=-79"/>
+        <parameter value="x_0=609601.22"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32120" name="NAD83 / North Dakota North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.73333333333333"/>
+        <parameter value="lat_2=47.43333333333333"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-100.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32121" name="NAD83 / North Dakota South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.48333333333333"/>
+        <parameter value="lat_2=46.18333333333333"/>
+        <parameter value="lat_0=45.66666666666666"/>
+        <parameter value="lon_0=-100.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32122" name="NAD83 / Ohio North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.7"/>
+        <parameter value="lat_2=40.43333333333333"/>
+        <parameter value="lat_0=39.66666666666666"/>
+        <parameter value="lon_0=-82.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32123" name="NAD83 / Ohio South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.03333333333333"/>
+        <parameter value="lat_2=38.73333333333333"/>
+        <parameter value="lat_0=38"/>
+        <parameter value="lon_0=-82.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32124" name="NAD83 / Oklahoma North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.76666666666667"/>
+        <parameter value="lat_2=35.56666666666667"/>
+        <parameter value="lat_0=35"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32125" name="NAD83 / Oklahoma South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=35.23333333333333"/>
+        <parameter value="lat_2=33.93333333333333"/>
+        <parameter value="lat_0=33.33333333333334"/>
+        <parameter value="lon_0=-98"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32126" name="NAD83 / Oregon North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46"/>
+        <parameter value="lat_2=44.33333333333334"/>
+        <parameter value="lat_0=43.66666666666666"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=2500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32127" name="NAD83 / Oregon South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44"/>
+        <parameter value="lat_2=42.33333333333334"/>
+        <parameter value="lat_0=41.66666666666666"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=1500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32128" name="NAD83 / Pennsylvania North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.95"/>
+        <parameter value="lat_2=40.88333333333333"/>
+        <parameter value="lat_0=40.16666666666666"/>
+        <parameter value="lon_0=-77.75"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32129" name="NAD83 / Pennsylvania South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.96666666666667"/>
+        <parameter value="lat_2=39.93333333333333"/>
+        <parameter value="lat_0=39.33333333333334"/>
+        <parameter value="lon_0=-77.75"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32130" name="NAD83 / Rhode Island">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=41.08333333333334"/>
+        <parameter value="lon_0=-71.5"/>
+        <parameter value="k=0.999994"/>
+        <parameter value="x_0=100000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32133" name="NAD83 / South Carolina">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=34.83333333333334"/>
+        <parameter value="lat_2=32.5"/>
+        <parameter value="lat_0=31.83333333333333"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="x_0=609600"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32134" name="NAD83 / South Dakota North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.68333333333333"/>
+        <parameter value="lat_2=44.41666666666666"/>
+        <parameter value="lat_0=43.83333333333334"/>
+        <parameter value="lon_0=-100"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32135" name="NAD83 / South Dakota South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.4"/>
+        <parameter value="lat_2=42.83333333333334"/>
+        <parameter value="lat_0=42.33333333333334"/>
+        <parameter value="lon_0=-100.3333333333333"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32136" name="NAD83 / Tennessee">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.41666666666666"/>
+        <parameter value="lat_2=35.25"/>
+        <parameter value="lat_0=34.33333333333334"/>
+        <parameter value="lon_0=-86"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32137" name="NAD83 / Texas North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=36.18333333333333"/>
+        <parameter value="lat_2=34.65"/>
+        <parameter value="lat_0=34"/>
+        <parameter value="lon_0=-101.5"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32138" name="NAD83 / Texas North Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=33.96666666666667"/>
+        <parameter value="lat_2=32.13333333333333"/>
+        <parameter value="lat_0=31.66666666666667"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=2000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32139" name="NAD83 / Texas Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=31.88333333333333"/>
+        <parameter value="lat_2=30.11666666666667"/>
+        <parameter value="lat_0=29.66666666666667"/>
+        <parameter value="lon_0=-100.3333333333333"/>
+        <parameter value="x_0=700000"/>
+        <parameter value="y_0=3000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32140" name="NAD83 / Texas South Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=30.28333333333333"/>
+        <parameter value="lat_2=28.38333333333333"/>
+        <parameter value="lat_0=27.83333333333333"/>
+        <parameter value="lon_0=-99"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=4000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32141" name="NAD83 / Texas South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=27.83333333333333"/>
+        <parameter value="lat_2=26.16666666666667"/>
+        <parameter value="lat_0=25.66666666666667"/>
+        <parameter value="lon_0=-98.5"/>
+        <parameter value="x_0=300000"/>
+        <parameter value="y_0=5000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32142" name="NAD83 / Utah North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=41.78333333333333"/>
+        <parameter value="lat_2=40.71666666666667"/>
+        <parameter value="lat_0=40.33333333333334"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32143" name="NAD83 / Utah Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.65"/>
+        <parameter value="lat_2=39.01666666666667"/>
+        <parameter value="lat_0=38.33333333333334"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=2000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32144" name="NAD83 / Utah South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.35"/>
+        <parameter value="lat_2=37.21666666666667"/>
+        <parameter value="lat_0=36.66666666666666"/>
+        <parameter value="lon_0=-111.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=3000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32145" name="NAD83 / Vermont">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=42.5"/>
+        <parameter value="lon_0=-72.5"/>
+        <parameter value="k=0.999964"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32146" name="NAD83 / Virginia North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=39.2"/>
+        <parameter value="lat_2=38.03333333333333"/>
+        <parameter value="lat_0=37.66666666666666"/>
+        <parameter value="lon_0=-78.5"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=2000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32147" name="NAD83 / Virginia South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=37.96666666666667"/>
+        <parameter value="lat_2=36.76666666666667"/>
+        <parameter value="lat_0=36.33333333333334"/>
+        <parameter value="lon_0=-78.5"/>
+        <parameter value="x_0=3500000"/>
+        <parameter value="y_0=1000000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32148" name="NAD83 / Washington North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=48.73333333333333"/>
+        <parameter value="lat_2=47.5"/>
+        <parameter value="lat_0=47"/>
+        <parameter value="lon_0=-120.8333333333333"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32149" name="NAD83 / Washington South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=47.33333333333334"/>
+        <parameter value="lat_2=45.83333333333334"/>
+        <parameter value="lat_0=45.33333333333334"/>
+        <parameter value="lon_0=-120.5"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32150" name="NAD83 / West Virginia North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=40.25"/>
+        <parameter value="lat_2=39"/>
+        <parameter value="lat_0=38.5"/>
+        <parameter value="lon_0=-79.5"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32151" name="NAD83 / West Virginia South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=38.88333333333333"/>
+        <parameter value="lat_2=37.48333333333333"/>
+        <parameter value="lat_0=37"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32152" name="NAD83 / Wisconsin North">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=46.76666666666667"/>
+        <parameter value="lat_2=45.56666666666667"/>
+        <parameter value="lat_0=45.16666666666666"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32153" name="NAD83 / Wisconsin Central">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=45.5"/>
+        <parameter value="lat_2=44.25"/>
+        <parameter value="lat_0=43.83333333333334"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32154" name="NAD83 / Wisconsin South">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=44.06666666666667"/>
+        <parameter value="lat_2=42.73333333333333"/>
+        <parameter value="lat_0=42"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32155" name="NAD83 / Wyoming East">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.5"/>
+        <parameter value="lon_0=-105.1666666666667"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32156" name="NAD83 / Wyoming East Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.5"/>
+        <parameter value="lon_0=-107.3333333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=400000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32157" name="NAD83 / Wyoming West Central">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.5"/>
+        <parameter value="lon_0=-108.75"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=600000"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32158" name="NAD83 / Wyoming West">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=40.5"/>
+        <parameter value="lon_0=-110.0833333333333"/>
+        <parameter value="k=0.999938"/>
+        <parameter value="x_0=800000"/>
+        <parameter value="y_0=100000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32161" name="NAD83 / Puerto Rico &amp; Virgin Is.">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=18.43333333333333"/>
+        <parameter value="lat_2=18.03333333333333"/>
+        <parameter value="lat_0=17.83333333333333"/>
+        <parameter value="lon_0=-66.43333333333334"/>
+        <parameter value="x_0=200000"/>
+        <parameter value="y_0=200000"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32180" name="NAD83 / SCoPQ zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-55.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32181" name="NAD83 / MTM zone 1">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-53"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32182" name="NAD83 / MTM zone 2">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-56"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32183" name="NAD83 / MTM zone 3">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-58.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32184" name="NAD83 / MTM zone 4">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-61.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32185" name="NAD83 / MTM zone 5">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-64.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32186" name="NAD83 / MTM zone 6">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-67.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32187" name="NAD83 / MTM zone 7">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-70.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32188" name="NAD83 / MTM zone 8">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-73.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32189" name="NAD83 / MTM zone 9">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-76.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32190" name="NAD83 / MTM zone 10">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-79.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32191" name="NAD83 / MTM zone 11">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-82.5"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32192" name="NAD83 / MTM zone 12">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-81"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32193" name="NAD83 / MTM zone 13">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-84"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32194" name="NAD83 / MTM zone 14">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-87"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32195" name="NAD83 / MTM zone 15">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-90"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32196" name="NAD83 / MTM zone 16">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-93"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32197" name="NAD83 / MTM zone 17">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=-96"/>
+        <parameter value="k=0.999900"/>
+        <parameter value="x_0=304800"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32198" name="NAD83 / Quebec Lambert">
+        <parameter value="proj=lcc"/>
+        <parameter value="lat_1=60"/>
+        <parameter value="lat_2=46"/>
+        <parameter value="lat_0=44"/>
+        <parameter value="lon_0=-68.5"/>
+        <parameter value="x_0=0"/>
+        <parameter value="y_0=0"/>
+        <parameter value="ellps=GRS80"/>
+        <parameter value="datum=NAD83"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32201" name="WGS 72 / UTM zone 1N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=1"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32202" name="WGS 72 / UTM zone 2N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=2"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32203" name="WGS 72 / UTM zone 3N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=3"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32204" name="WGS 72 / UTM zone 4N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=4"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32205" name="WGS 72 / UTM zone 5N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=5"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32206" name="WGS 72 / UTM zone 6N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=6"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32207" name="WGS 72 / UTM zone 7N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=7"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32208" name="WGS 72 / UTM zone 8N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=8"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32209" name="WGS 72 / UTM zone 9N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=9"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32210" name="WGS 72 / UTM zone 10N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=10"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32211" name="WGS 72 / UTM zone 11N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=11"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32212" name="WGS 72 / UTM zone 12N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=12"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32213" name="WGS 72 / UTM zone 13N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=13"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32214" name="WGS 72 / UTM zone 14N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=14"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32215" name="WGS 72 / UTM zone 15N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=15"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32216" name="WGS 72 / UTM zone 16N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=16"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32217" name="WGS 72 / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32218" name="WGS 72 / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32219" name="WGS 72 / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32220" name="WGS 72 / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32221" name="WGS 72 / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32222" name="WGS 72 / UTM zone 22N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32223" name="WGS 72 / UTM zone 23N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32224" name="WGS 72 / UTM zone 24N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=24"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32225" name="WGS 72 / UTM zone 25N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=25"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32226" name="WGS 72 / UTM zone 26N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=26"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32227" name="WGS 72 / UTM zone 27N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=27"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32228" name="WGS 72 / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32229" name="WGS 72 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32230" name="WGS 72 / UTM zone 30N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32231" name="WGS 72 / UTM zone 31N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32232" name="WGS 72 / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32233" name="WGS 72 / UTM zone 33N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32234" name="WGS 72 / UTM zone 34N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32235" name="WGS 72 / UTM zone 35N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32236" name="WGS 72 / UTM zone 36N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32237" name="WGS 72 / UTM zone 37N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32238" name="WGS 72 / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32239" name="WGS 72 / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32240" name="WGS 72 / UTM zone 40N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32241" name="WGS 72 / UTM zone 41N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=41"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32242" name="WGS 72 / UTM zone 42N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=42"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32243" name="WGS 72 / UTM zone 43N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=43"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32244" name="WGS 72 / UTM zone 44N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=44"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32245" name="WGS 72 / UTM zone 45N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=45"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32246" name="WGS 72 / UTM zone 46N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32247" name="WGS 72 / UTM zone 47N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32248" name="WGS 72 / UTM zone 48N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32249" name="WGS 72 / UTM zone 49N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32250" name="WGS 72 / UTM zone 50N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32251" name="WGS 72 / UTM zone 51N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32252" name="WGS 72 / UTM zone 52N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32253" name="WGS 72 / UTM zone 53N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32254" name="WGS 72 / UTM zone 54N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=54"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32255" name="WGS 72 / UTM zone 55N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=55"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32256" name="WGS 72 / UTM zone 56N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=56"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32257" name="WGS 72 / UTM zone 57N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=57"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32258" name="WGS 72 / UTM zone 58N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32259" name="WGS 72 / UTM zone 59N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=59"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32260" name="WGS 72 / UTM zone 60N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=60"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32301" name="WGS 72 / UTM zone 1S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=1"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32302" name="WGS 72 / UTM zone 2S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=2"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32303" name="WGS 72 / UTM zone 3S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=3"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32304" name="WGS 72 / UTM zone 4S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=4"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32305" name="WGS 72 / UTM zone 5S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=5"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32306" name="WGS 72 / UTM zone 6S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=6"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32307" name="WGS 72 / UTM zone 7S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=7"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32308" name="WGS 72 / UTM zone 8S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=8"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32309" name="WGS 72 / UTM zone 9S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=9"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32310" name="WGS 72 / UTM zone 10S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=10"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32311" name="WGS 72 / UTM zone 11S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=11"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32312" name="WGS 72 / UTM zone 12S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=12"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32313" name="WGS 72 / UTM zone 13S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=13"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32314" name="WGS 72 / UTM zone 14S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=14"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32315" name="WGS 72 / UTM zone 15S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=15"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32316" name="WGS 72 / UTM zone 16S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=16"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32317" name="WGS 72 / UTM zone 17S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32318" name="WGS 72 / UTM zone 18S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32319" name="WGS 72 / UTM zone 19S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32320" name="WGS 72 / UTM zone 20S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32321" name="WGS 72 / UTM zone 21S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32322" name="WGS 72 / UTM zone 22S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32323" name="WGS 72 / UTM zone 23S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32324" name="WGS 72 / UTM zone 24S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=24"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32325" name="WGS 72 / UTM zone 25S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=25"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32326" name="WGS 72 / UTM zone 26S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=26"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32327" name="WGS 72 / UTM zone 27S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=27"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32328" name="WGS 72 / UTM zone 28S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32329" name="WGS 72 / UTM zone 29S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32330" name="WGS 72 / UTM zone 30S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32331" name="WGS 72 / UTM zone 31S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32332" name="WGS 72 / UTM zone 32S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32333" name="WGS 72 / UTM zone 33S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32334" name="WGS 72 / UTM zone 34S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32335" name="WGS 72 / UTM zone 35S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32336" name="WGS 72 / UTM zone 36S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32337" name="WGS 72 / UTM zone 37S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32338" name="WGS 72 / UTM zone 38S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32339" name="WGS 72 / UTM zone 39S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32340" name="WGS 72 / UTM zone 40S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32341" name="WGS 72 / UTM zone 41S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=41"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32342" name="WGS 72 / UTM zone 42S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=42"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32343" name="WGS 72 / UTM zone 43S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=43"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32344" name="WGS 72 / UTM zone 44S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=44"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32345" name="WGS 72 / UTM zone 45S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=45"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32346" name="WGS 72 / UTM zone 46S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32347" name="WGS 72 / UTM zone 47S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32348" name="WGS 72 / UTM zone 48S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32349" name="WGS 72 / UTM zone 49S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32350" name="WGS 72 / UTM zone 50S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32351" name="WGS 72 / UTM zone 51S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32352" name="WGS 72 / UTM zone 52S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32353" name="WGS 72 / UTM zone 53S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32354" name="WGS 72 / UTM zone 54S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=54"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32355" name="WGS 72 / UTM zone 55S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=55"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32356" name="WGS 72 / UTM zone 56S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=56"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32357" name="WGS 72 / UTM zone 57S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=57"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32358" name="WGS 72 / UTM zone 58S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32359" name="WGS 72 / UTM zone 59S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=59"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32360" name="WGS 72 / UTM zone 60S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=60"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32401" name="WGS 72BE / UTM zone 1N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=1"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32402" name="WGS 72BE / UTM zone 2N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=2"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32403" name="WGS 72BE / UTM zone 3N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=3"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32404" name="WGS 72BE / UTM zone 4N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=4"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32405" name="WGS 72BE / UTM zone 5N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=5"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32406" name="WGS 72BE / UTM zone 6N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=6"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32407" name="WGS 72BE / UTM zone 7N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=7"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32408" name="WGS 72BE / UTM zone 8N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=8"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32409" name="WGS 72BE / UTM zone 9N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=9"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32410" name="WGS 72BE / UTM zone 10N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=10"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32411" name="WGS 72BE / UTM zone 11N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=11"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32412" name="WGS 72BE / UTM zone 12N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=12"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32413" name="WGS 72BE / UTM zone 13N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=13"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32414" name="WGS 72BE / UTM zone 14N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=14"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32415" name="WGS 72BE / UTM zone 15N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=15"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32416" name="WGS 72BE / UTM zone 16N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=16"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32417" name="WGS 72BE / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32418" name="WGS 72BE / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32419" name="WGS 72BE / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32420" name="WGS 72BE / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32421" name="WGS 72BE / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32422" name="WGS 72BE / UTM zone 22N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32423" name="WGS 72BE / UTM zone 23N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32424" name="WGS 72BE / UTM zone 24N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=24"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32425" name="WGS 72BE / UTM zone 25N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=25"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32426" name="WGS 72BE / UTM zone 26N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=26"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32427" name="WGS 72BE / UTM zone 27N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=27"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32428" name="WGS 72BE / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32429" name="WGS 72BE / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32430" name="WGS 72BE / UTM zone 30N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32431" name="WGS 72BE / UTM zone 31N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32432" name="WGS 72BE / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32433" name="WGS 72BE / UTM zone 33N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32434" name="WGS 72BE / UTM zone 34N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32435" name="WGS 72BE / UTM zone 35N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32436" name="WGS 72BE / UTM zone 36N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32437" name="WGS 72BE / UTM zone 37N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32438" name="WGS 72BE / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32439" name="WGS 72BE / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32440" name="WGS 72BE / UTM zone 40N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32441" name="WGS 72BE / UTM zone 41N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=41"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32442" name="WGS 72BE / UTM zone 42N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=42"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32443" name="WGS 72BE / UTM zone 43N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=43"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32444" name="WGS 72BE / UTM zone 44N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=44"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32445" name="WGS 72BE / UTM zone 45N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=45"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32446" name="WGS 72BE / UTM zone 46N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32447" name="WGS 72BE / UTM zone 47N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32448" name="WGS 72BE / UTM zone 48N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32449" name="WGS 72BE / UTM zone 49N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32450" name="WGS 72BE / UTM zone 50N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32451" name="WGS 72BE / UTM zone 51N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32452" name="WGS 72BE / UTM zone 52N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32453" name="WGS 72BE / UTM zone 53N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32454" name="WGS 72BE / UTM zone 54N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=54"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32455" name="WGS 72BE / UTM zone 55N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=55"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32456" name="WGS 72BE / UTM zone 56N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=56"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32457" name="WGS 72BE / UTM zone 57N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=57"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32458" name="WGS 72BE / UTM zone 58N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32459" name="WGS 72BE / UTM zone 59N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=59"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32460" name="WGS 72BE / UTM zone 60N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=60"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32501" name="WGS 72BE / UTM zone 1S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=1"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32502" name="WGS 72BE / UTM zone 2S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=2"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32503" name="WGS 72BE / UTM zone 3S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=3"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32504" name="WGS 72BE / UTM zone 4S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=4"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32505" name="WGS 72BE / UTM zone 5S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=5"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32506" name="WGS 72BE / UTM zone 6S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=6"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32507" name="WGS 72BE / UTM zone 7S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=7"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32508" name="WGS 72BE / UTM zone 8S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=8"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32509" name="WGS 72BE / UTM zone 9S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=9"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32510" name="WGS 72BE / UTM zone 10S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=10"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32511" name="WGS 72BE / UTM zone 11S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=11"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32512" name="WGS 72BE / UTM zone 12S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=12"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32513" name="WGS 72BE / UTM zone 13S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=13"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32514" name="WGS 72BE / UTM zone 14S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=14"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32515" name="WGS 72BE / UTM zone 15S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=15"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32516" name="WGS 72BE / UTM zone 16S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=16"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32517" name="WGS 72BE / UTM zone 17S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32518" name="WGS 72BE / UTM zone 18S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32519" name="WGS 72BE / UTM zone 19S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32520" name="WGS 72BE / UTM zone 20S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32521" name="WGS 72BE / UTM zone 21S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32522" name="WGS 72BE / UTM zone 22S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32523" name="WGS 72BE / UTM zone 23S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32524" name="WGS 72BE / UTM zone 24S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=24"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32525" name="WGS 72BE / UTM zone 25S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=25"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32526" name="WGS 72BE / UTM zone 26S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=26"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32527" name="WGS 72BE / UTM zone 27S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=27"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32528" name="WGS 72BE / UTM zone 28S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32529" name="WGS 72BE / UTM zone 29S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32530" name="WGS 72BE / UTM zone 30S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32531" name="WGS 72BE / UTM zone 31S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32532" name="WGS 72BE / UTM zone 32S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32533" name="WGS 72BE / UTM zone 33S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32534" name="WGS 72BE / UTM zone 34S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32535" name="WGS 72BE / UTM zone 35S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32536" name="WGS 72BE / UTM zone 36S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32537" name="WGS 72BE / UTM zone 37S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32538" name="WGS 72BE / UTM zone 38S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32539" name="WGS 72BE / UTM zone 39S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32540" name="WGS 72BE / UTM zone 40S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32541" name="WGS 72BE / UTM zone 41S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=41"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32542" name="WGS 72BE / UTM zone 42S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=42"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32543" name="WGS 72BE / UTM zone 43S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=43"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32544" name="WGS 72BE / UTM zone 44S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=44"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32545" name="WGS 72BE / UTM zone 45S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=45"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32546" name="WGS 72BE / UTM zone 46S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32547" name="WGS 72BE / UTM zone 47S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32548" name="WGS 72BE / UTM zone 48S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32549" name="WGS 72BE / UTM zone 49S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32550" name="WGS 72BE / UTM zone 50S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32551" name="WGS 72BE / UTM zone 51S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32552" name="WGS 72BE / UTM zone 52S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32553" name="WGS 72BE / UTM zone 53S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32554" name="WGS 72BE / UTM zone 54S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=54"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32555" name="WGS 72BE / UTM zone 55S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=55"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32556" name="WGS 72BE / UTM zone 56S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=56"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32557" name="WGS 72BE / UTM zone 57S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=57"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32558" name="WGS 72BE / UTM zone 58S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32559" name="WGS 72BE / UTM zone 59S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=59"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32560" name="WGS 72BE / UTM zone 60S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=60"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS72"/>
+        <parameter value="towgs84=0,0,1.9,0,0,0.814,-0.38"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32601" name="WGS 84 / UTM zone 1N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=1"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32602" name="WGS 84 / UTM zone 2N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=2"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32603" name="WGS 84 / UTM zone 3N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=3"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32604" name="WGS 84 / UTM zone 4N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=4"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32605" name="WGS 84 / UTM zone 5N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=5"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32606" name="WGS 84 / UTM zone 6N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=6"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32607" name="WGS 84 / UTM zone 7N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=7"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32608" name="WGS 84 / UTM zone 8N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=8"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32609" name="WGS 84 / UTM zone 9N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=9"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32610" name="WGS 84 / UTM zone 10N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=10"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32611" name="WGS 84 / UTM zone 11N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=11"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32612" name="WGS 84 / UTM zone 12N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=12"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32613" name="WGS 84 / UTM zone 13N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=13"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32614" name="WGS 84 / UTM zone 14N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=14"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32615" name="WGS 84 / UTM zone 15N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=15"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32616" name="WGS 84 / UTM zone 16N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=16"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32617" name="WGS 84 / UTM zone 17N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32618" name="WGS 84 / UTM zone 18N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32619" name="WGS 84 / UTM zone 19N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32620" name="WGS 84 / UTM zone 20N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32621" name="WGS 84 / UTM zone 21N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32622" name="WGS 84 / UTM zone 22N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32623" name="WGS 84 / UTM zone 23N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32624" name="WGS 84 / UTM zone 24N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=24"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32625" name="WGS 84 / UTM zone 25N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=25"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32626" name="WGS 84 / UTM zone 26N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=26"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32627" name="WGS 84 / UTM zone 27N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=27"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32628" name="WGS 84 / UTM zone 28N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32629" name="WGS 84 / UTM zone 29N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32630" name="WGS 84 / UTM zone 30N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32631" name="WGS 84 / UTM zone 31N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32632" name="WGS 84 / UTM zone 32N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32633" name="WGS 84 / UTM zone 33N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32634" name="WGS 84 / UTM zone 34N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32635" name="WGS 84 / UTM zone 35N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32636" name="WGS 84 / UTM zone 36N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32637" name="WGS 84 / UTM zone 37N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32638" name="WGS 84 / UTM zone 38N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32639" name="WGS 84 / UTM zone 39N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32640" name="WGS 84 / UTM zone 40N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32641" name="WGS 84 / UTM zone 41N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=41"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32642" name="WGS 84 / UTM zone 42N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=42"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32643" name="WGS 84 / UTM zone 43N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=43"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32644" name="WGS 84 / UTM zone 44N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=44"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32645" name="WGS 84 / UTM zone 45N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=45"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32646" name="WGS 84 / UTM zone 46N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32647" name="WGS 84 / UTM zone 47N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32648" name="WGS 84 / UTM zone 48N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32649" name="WGS 84 / UTM zone 49N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32650" name="WGS 84 / UTM zone 50N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32651" name="WGS 84 / UTM zone 51N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32652" name="WGS 84 / UTM zone 52N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32653" name="WGS 84 / UTM zone 53N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32654" name="WGS 84 / UTM zone 54N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=54"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32655" name="WGS 84 / UTM zone 55N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=55"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32656" name="WGS 84 / UTM zone 56N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=56"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32657" name="WGS 84 / UTM zone 57N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=57"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32658" name="WGS 84 / UTM zone 58N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32659" name="WGS 84 / UTM zone 59N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=59"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32660" name="WGS 84 / UTM zone 60N">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=60"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32661" name="WGS 84 / UPS North">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=90"/>
+        <parameter value="lat_ts=90"/>
+        <parameter value="lon_0=0"/>
+        <parameter value="k=0.994"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=2000000"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32701" name="WGS 84 / UTM zone 1S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=1"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32702" name="WGS 84 / UTM zone 2S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=2"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32703" name="WGS 84 / UTM zone 3S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=3"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32704" name="WGS 84 / UTM zone 4S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=4"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32705" name="WGS 84 / UTM zone 5S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=5"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32706" name="WGS 84 / UTM zone 6S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=6"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32707" name="WGS 84 / UTM zone 7S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=7"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32708" name="WGS 84 / UTM zone 8S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=8"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32709" name="WGS 84 / UTM zone 9S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=9"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32710" name="WGS 84 / UTM zone 10S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=10"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32711" name="WGS 84 / UTM zone 11S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=11"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32712" name="WGS 84 / UTM zone 12S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=12"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32713" name="WGS 84 / UTM zone 13S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=13"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32714" name="WGS 84 / UTM zone 14S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=14"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32715" name="WGS 84 / UTM zone 15S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=15"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32716" name="WGS 84 / UTM zone 16S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=16"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32717" name="WGS 84 / UTM zone 17S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=17"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32718" name="WGS 84 / UTM zone 18S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=18"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32719" name="WGS 84 / UTM zone 19S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=19"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32720" name="WGS 84 / UTM zone 20S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=20"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32721" name="WGS 84 / UTM zone 21S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=21"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32722" name="WGS 84 / UTM zone 22S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=22"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32723" name="WGS 84 / UTM zone 23S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=23"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32724" name="WGS 84 / UTM zone 24S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=24"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32725" name="WGS 84 / UTM zone 25S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=25"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32726" name="WGS 84 / UTM zone 26S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=26"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32727" name="WGS 84 / UTM zone 27S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=27"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32728" name="WGS 84 / UTM zone 28S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=28"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32729" name="WGS 84 / UTM zone 29S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=29"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32730" name="WGS 84 / UTM zone 30S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=30"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32731" name="WGS 84 / UTM zone 31S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=31"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32732" name="WGS 84 / UTM zone 32S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=32"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32733" name="WGS 84 / UTM zone 33S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=33"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32734" name="WGS 84 / UTM zone 34S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=34"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32735" name="WGS 84 / UTM zone 35S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=35"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32736" name="WGS 84 / UTM zone 36S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=36"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32737" name="WGS 84 / UTM zone 37S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=37"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32738" name="WGS 84 / UTM zone 38S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=38"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32739" name="WGS 84 / UTM zone 39S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=39"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32740" name="WGS 84 / UTM zone 40S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=40"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32741" name="WGS 84 / UTM zone 41S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=41"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32742" name="WGS 84 / UTM zone 42S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=42"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32743" name="WGS 84 / UTM zone 43S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=43"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32744" name="WGS 84 / UTM zone 44S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=44"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32745" name="WGS 84 / UTM zone 45S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=45"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32746" name="WGS 84 / UTM zone 46S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=46"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32747" name="WGS 84 / UTM zone 47S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=47"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32748" name="WGS 84 / UTM zone 48S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=48"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32749" name="WGS 84 / UTM zone 49S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=49"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32750" name="WGS 84 / UTM zone 50S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=50"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32751" name="WGS 84 / UTM zone 51S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=51"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32752" name="WGS 84 / UTM zone 52S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=52"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32753" name="WGS 84 / UTM zone 53S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=53"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32754" name="WGS 84 / UTM zone 54S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=54"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32755" name="WGS 84 / UTM zone 55S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=55"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32756" name="WGS 84 / UTM zone 56S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=56"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32757" name="WGS 84 / UTM zone 57S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=57"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32758" name="WGS 84 / UTM zone 58S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=58"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32759" name="WGS 84 / UTM zone 59S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=59"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32760" name="WGS 84 / UTM zone 60S">
+        <parameter value="proj=utm"/>
+        <parameter value="zone=60"/>
+        <parameter value="south"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32761" name="WGS 84 / UPS South">
+        <parameter value="proj=stere"/>
+        <parameter value="lat_0=-90"/>
+        <parameter value="lat_ts=-90"/>
+        <parameter value="lon_0=0"/>
+        <parameter value="k=0.994"/>
+        <parameter value="x_0=2000000"/>
+        <parameter value="y_0=2000000"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+    <projection epsg="32766" name="WGS 84 / TM 36 SE">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0"/>
+        <parameter value="lon_0=36"/>
+        <parameter value="k=0.999600"/>
+        <parameter value="x_0=500000"/>
+        <parameter value="y_0=10000000"/>
+        <parameter value="ellps=WGS84"/>
+        <parameter value="datum=WGS84"/>
+        <parameter value="units=m"/>
+        <parameter value="no_defs"/>
+    </projection>
+</projectionlist>

Added: packages/thuban/branches/upstream/current/Resources/XML/projfile.dtd
===================================================================
--- packages/thuban/branches/upstream/current/Resources/XML/projfile.dtd	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/XML/projfile.dtd	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- projfile.dtd
+
+    Copyright (C) 2003 by Intevation GmbH
+    Authors:
+        Bernhard Herzog <bh at intevation.de>
+
+    This program is free software under the GPL (>=v2)
+    Read the file COPYING coming with Thuban for details.
+
+    $Revision: 1817 $
+    $Source$
+    $Id: projfile.dtd 1817 2003-10-13 15:54:02Z bh $
+-->
+
+<!-- a projfile is a list of projections. The projections are stored in
+    the same way as in a .thuban file
+ -->
+
+<!ELEMENT projectionlist (projection*)>
+
+<!ELEMENT projection (parameter*)>
+<!ATTLIST projection 
+        name CDATA "" 
+        epsg CDATA #IMPLIED >
+
+<!ELEMENT parameter EMPTY>
+<!ATTLIST parameter value CDATA #REQUIRED>

Added: packages/thuban/branches/upstream/current/Resources/XML/thuban-0.8.dtd
===================================================================
--- packages/thuban/branches/upstream/current/Resources/XML/thuban-0.8.dtd	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/XML/thuban-0.8.dtd	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--    thuban-0.8.dtd
+
+    Copyright (C) 2001, 2003 by Intevation GmbH
+    Authors:
+	Jan-Oliver Wagner <jan at intevation.de>
+        Bernhard Herzog <bh at intevation.de>
+
+    This program is free software under the GPL (>=v2)
+    Read the file COPYING coming with Thuban for details.
+-->
+
+<!-- a session contains zero or more datasources and and zero or more maps
+
+At some point, the namespace attribute will likely be used by Thuban to
+identify the version of the file format. 
+-->
+
+<!ENTITY % shapesources "fileshapesource | derivedshapesource">
+<!ENTITY % tables "filetable | jointable">
+<!ELEMENT session ((%shapesources; | %tables; )*, map*)>
+<!ATTLIST session 
+        title CDATA #REQUIRED
+        xmlns CDATA #IMPLIED
+>
+
+
+<!-- 
+    A fileshapesource is a source of shapes and perhaps attribute data
+    read from a file. The filetype attribute must be one of the
+    supported file types. Currently only "shapefile" is supported.
+ -->
+
+<!ELEMENT fileshapesource EMPTY>
+<!ATTLIST fileshapesource
+        id       ID   #REQUIRED
+        filename CDATA #REQUIRED
+        filetype CDATA #REQUIRED
+>
+
+<!--
+     A derivedshapesource is a source of shapes and attribute data
+    derived from another shapesource for the shapes and a table for the
+    attribute data.
+ -->
+
+<!ELEMENT derivedshapesource EMPTY>
+<!ATTLIST derivedshapesource
+        id          ID   #REQUIRED
+        shapesource IDREF #REQUIRED
+        table       IDREF #REQUIRED
+>
+
+
+<!-- a filetable points to the actual file that
+	contains the tabular data.
+
+     The filetype Attribute may be onve of "DBF" or "CSV"
+-->
+<!ELEMENT filetable EMPTY>
+<!ATTLIST filetable 
+        id       ID    #REQUIRED
+        title    CDATA #REQUIRED
+        filename CDATA #REQUIRED
+        filetype CDATA #REQUIRED>
+
+<!-- 
+    A jointable is a table with the result of something equivalent to
+    this SQL Statement:
+
+     SELECT * FROM left JOIN right WHERE left.leftcolumn = right.rightcolumn;
+
+    The attributes left and right must be the ids of two tables defined
+    previously in the XML-Document file. leftcolumn and rightcolumn are 
+    the column names to join on.
+-->
+<!ELEMENT jointable EMPTY>
+<!ATTLIST jointable
+        id          ID    #REQUIRED
+        title       CDATA #REQUIRED
+        left        IDREF #REQUIRED
+        leftcolumn  CDATA #REQUIRED
+        right       IDREF #REQUIRED
+        rightcolumn CDATA #REQUIRED
+>
+
+<!-- A Map
+
+        A map consists of a number of layers
+	the projection refers to the projection
+	used to display the map. If the projection
+	is missing, geographic coordinates in decimal
+	degrees are assumed.
+-->
+<!ELEMENT map (projection?, (layer | rasterlayer)*, labellayer?)>
+<!ATTLIST map title CDATA #REQUIRED>
+
+<!-- a layer represents a set of geographic objects.
+	pointers to the actual data are stored.
+	The shapestore attributes contains the id of the data store
+        shown in the layer.
+	the projection refers to the projection
+	in which the data are stored. If the projection
+	is missing, geographic coordinates in decimal
+	degrees are assumed. Visibility is assumed true
+    unless otherwise specified.
+-->
+<!ELEMENT layer (projection?, classification?)>
+<!ATTLIST layer title CDATA #REQUIRED>
+<!ATTLIST layer shapestore IDREF #REQUIRED>
+<!ATTLIST layer visible (true|false) "true">
+<!-- the fill and stroke attributes can be either "None" or "#RRGGBB"
+     RGB hex values
+
+     All of fill, stroke and stroke_width may be omitted and default to
+     "None", "#000000" and "1" respectively.
+ -->
+<!ATTLIST layer fill CDATA "None">
+<!ATTLIST layer stroke CDATA "#000000">
+<!ATTLIST layer stroke_width CDATA "1">
+
+
+<!-- a rasterlayer represents an image that has some geographic data
+    associated with it. The filename points to the image used.
+-->
+<!ELEMENT rasterlayer (projection?, classification?)>
+<!ATTLIST rasterlayer 
+        title    CDATA #REQUIRED
+        filename CDATA #REQUIRED
+        visible  (true|false) "true">
+
+
+<!-- Classification data -->
+<!ELEMENT classification (clnull?, clpoint*, clrange*, clcont*)>
+<!ATTLIST classification field CDATA #REQUIRED>
+<!ATTLIST classification field_type CDATA #REQUIRED>
+
+<!ELEMENT clnull (cldata*)>
+<!ELEMENT clpoint (cldata*)>
+<!ELEMENT clrange (cldata*)>
+<!ELEMENT clcont (cldata*)>
+
+<!ATTLIST clnull label CDATA #IMPLIED>
+
+<!ATTLIST clpoint value CDATA #REQUIRED>
+<!ATTLIST clpoint label CDATA #IMPLIED>
+
+<!ATTLIST clrange min CDATA #IMPLIED>
+<!ATTLIST clrange max CDATA #IMPLIED>
+<!ATTLIST clrange range CDATA #IMPLIED>
+<!ATTLIST clrange label CDATA #IMPLIED>
+
+<!ATTLIST clcont rmin CDATA #REQUIRED>
+<!ATTLIST clcont rmax CDATA #REQUIRED>
+<!ATTLIST clcont dmin CDATA #REQUIRED>
+<!ATTLIST clcont dmax CDATA #REQUIRED>
+
+<!-- Visual appearance of the classification 
+
+     the fill and stroke attributes can be either "None" or "#RRGGBB"
+     RGB hex values
+
+     All of fill, stroke and stroke_width may be omitted and default to
+     "None", "#000000" and "1" respectively.
+ -->
+<!ELEMENT cldata EMPTY>
+<!ATTLIST cldata 
+        stroke       CDATA #IMPLIED
+        stroke_width CDATA #IMPLIED
+        fill         CDATA #IMPLIED
+>
+
+
+<!-- a projection has a number of parameters
+-->
+<!ELEMENT projection (parameter*)>
+<!ATTLIST projection
+        name CDATA "" >
+
+<!-- just a simple parameter consisting of a value
+-->
+<!ELEMENT parameter EMPTY>
+<!ATTLIST parameter value CDATA #REQUIRED>
+
+
+<!-- The label layer contains text labels -->
+<!ELEMENT labellayer (label*) >
+
+<!ELEMENT label EMPTY>
+<!ATTLIST label
+        x CDATA #REQUIRED
+        y CDATA #REQUIRED
+        text CDATA #REQUIRED
+        halign (left|center|right) #REQUIRED
+        valign (top|center|bottom) #REQUIRED>

Added: packages/thuban/branches/upstream/current/Resources/XML/thuban-0.9.dtd
===================================================================
--- packages/thuban/branches/upstream/current/Resources/XML/thuban-0.9.dtd	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/XML/thuban-0.9.dtd	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--    thuban-0.9.dtd
+
+    Copyright (C) 2001, 2003 by Intevation GmbH
+    Authors:
+	Jan-Oliver Wagner <jan at intevation.de>
+        Bernhard Herzog <bh at intevation.de>
+
+    This program is free software under the GPL (>=v2)
+    Read the file COPYING coming with Thuban for details.
+-->
+
+<!-- a session contains zero or more database connections zero or more
+     datasources and and zero or more maps
+
+At some point, the namespace attribute will likely be used by Thuban to
+identify the version of the file format. 
+-->
+
+<!ENTITY % shapesources "fileshapesource | derivedshapesource | dbshapesource">
+<!ENTITY % tables "filetable | jointable">
+<!ELEMENT session ((dbconnection | %shapesources; | %tables; )*, map*)>
+<!ATTLIST session 
+        title CDATA #REQUIRED
+        xmlns CDATA #IMPLIED
+>
+
+
+<!--
+    A db connection represents the connection to a database.
+
+    Currently only connections to postgis databases are supported and
+    thus The dbtype attribute must be "postgis".
+-->
+
+<!ELEMENT dbconnection EMPTY>
+<!ATTLIST dbconnection
+        id     ID    #REQUIRED
+        dbtype CDATA #REQUIRED
+        dbname CDATA #REQUIRED
+        host   CDATA ""
+        port   CDATA ""
+        user   CDATA ""
+>
+
+
+<!-- A dbshapesource represents a table with geometry data in a database
+
+     The dbconn attribute must be the id of a dbconnection element
+     occurring earlier in the document.
+-->
+
+<!ELEMENT dbshapesource EMPTY>
+<!ATTLIST dbshapesource
+        id        ID    #REQUIRED
+        dbconn    IDREF #REQUIRED
+        tablename CDATA #REQUIRED
+>
+
+<!-- 
+    A fileshapesource is a source of shapes and perhaps attribute data
+    read from a file. The filetype attribute must be one of the
+    supported file types. Currently only "shapefile" is supported.
+ -->
+
+<!ELEMENT fileshapesource EMPTY>
+<!ATTLIST fileshapesource
+        id       ID   #REQUIRED
+        filename CDATA #REQUIRED
+        filetype CDATA #REQUIRED
+>
+
+<!--
+     A derivedshapesource is a source of shapes and attribute data
+    derived from another shapesource for the shapes and a table for the
+    attribute data.
+ -->
+
+<!ELEMENT derivedshapesource EMPTY>
+<!ATTLIST derivedshapesource
+        id          ID   #REQUIRED
+        shapesource IDREF #REQUIRED
+        table       IDREF #REQUIRED
+>
+
+
+<!-- a filetable points to the actual file that
+	contains the tabular data.
+
+     The filetype Attribute may be onve of "DBF" or "CSV"
+-->
+<!ELEMENT filetable EMPTY>
+<!ATTLIST filetable 
+        id       ID    #REQUIRED
+        title    CDATA #REQUIRED
+        filename CDATA #REQUIRED
+        filetype CDATA #REQUIRED>
+
+<!-- 
+    A jointable is a table with the result of something equivalent to
+    this SQL Statement:
+
+     SELECT * FROM left JOIN right WHERE left.leftcolumn = right.rightcolumn;
+
+    The attributes left and right must be the ids of two tables defined
+    previously in the XML-Document file. leftcolumn and rightcolumn are 
+    the column names to join on.
+
+    The jointype attribute should be either "INNER" or "LEFT OUTER".
+-->
+<!ELEMENT jointable EMPTY>
+<!ATTLIST jointable
+        id          ID    #REQUIRED
+        title       CDATA #REQUIRED
+        left        IDREF #REQUIRED
+        leftcolumn  CDATA #REQUIRED
+        right       IDREF #REQUIRED
+        rightcolumn CDATA #REQUIRED
+        jointype    CDATA #REQUIRED
+>
+
+<!-- A Map
+
+        A map consists of a number of layers
+	the projection refers to the projection
+	used to display the map. If the projection
+	is missing, geographic coordinates in decimal
+	degrees are assumed.
+-->
+<!ELEMENT map (projection?, (layer | rasterlayer)*, labellayer?)>
+<!ATTLIST map title CDATA #REQUIRED>
+
+<!-- a layer represents a set of geographic objects.
+	pointers to the actual data are stored.
+	The shapestore attributes contains the id of the data store
+        shown in the layer.
+	the projection refers to the projection
+	in which the data are stored. If the projection
+	is missing, geographic coordinates in decimal
+	degrees are assumed. Visibility is assumed true
+    unless otherwise specified.
+-->
+<!ELEMENT layer (projection?, classification?)>
+<!ATTLIST layer title CDATA #REQUIRED>
+<!ATTLIST layer shapestore IDREF #REQUIRED>
+<!ATTLIST layer visible (true|false) "true">
+<!-- the fill and stroke attributes can be either "None" or "#RRGGBB"
+     RGB hex values
+
+     All of fill, stroke and stroke_width may be omitted and default to
+     "None", "#000000" and "1" respectively.
+ -->
+<!ATTLIST layer fill CDATA "None">
+<!ATTLIST layer stroke CDATA "#000000">
+<!ATTLIST layer stroke_width CDATA "1">
+
+
+<!-- a rasterlayer represents an image that has some geographic data
+    associated with it. The filename points to the image used.
+-->
+<!ELEMENT rasterlayer (projection?, classification?)>
+<!ATTLIST rasterlayer 
+        title    CDATA #REQUIRED
+        filename CDATA #REQUIRED
+        visible  (true|false) "true">
+
+
+<!-- Classification data -->
+<!ELEMENT classification (clnull?, clpoint*, clrange*, clcont*)>
+<!ATTLIST classification field CDATA #REQUIRED>
+<!ATTLIST classification field_type CDATA #REQUIRED>
+
+<!ELEMENT clnull (cldata*)>
+<!ELEMENT clpoint (cldata*)>
+<!ELEMENT clrange (cldata*)>
+<!ELEMENT clcont (cldata*)>
+
+<!ATTLIST clnull label CDATA #IMPLIED>
+
+<!ATTLIST clpoint value CDATA #REQUIRED>
+<!ATTLIST clpoint label CDATA #IMPLIED>
+
+<!ATTLIST clrange min CDATA #IMPLIED>
+<!ATTLIST clrange max CDATA #IMPLIED>
+<!ATTLIST clrange range CDATA #IMPLIED>
+<!ATTLIST clrange label CDATA #IMPLIED>
+
+<!ATTLIST clcont rmin CDATA #REQUIRED>
+<!ATTLIST clcont rmax CDATA #REQUIRED>
+<!ATTLIST clcont dmin CDATA #REQUIRED>
+<!ATTLIST clcont dmax CDATA #REQUIRED>
+
+<!-- Visual appearance of the classification 
+
+     the fill and stroke attributes can be either "None" or "#RRGGBB"
+     RGB hex values
+
+     All of fill, stroke and stroke_width may be omitted and default to
+     "None", "#000000" and "1" respectively.
+ -->
+<!ELEMENT cldata EMPTY>
+<!ATTLIST cldata 
+        stroke       CDATA #IMPLIED
+        stroke_width CDATA #IMPLIED
+        fill         CDATA #IMPLIED
+>
+
+
+<!-- a projection has a number of parameters
+-->
+<!ELEMENT projection (parameter*)>
+<!ATTLIST projection
+        name CDATA "" >
+
+<!-- just a simple parameter consisting of a value
+-->
+<!ELEMENT parameter EMPTY>
+<!ATTLIST parameter value CDATA #REQUIRED>
+
+
+<!-- The label layer contains text labels -->
+<!ELEMENT labellayer (label*) >
+
+<!ELEMENT label EMPTY>
+<!ATTLIST label
+        x CDATA #REQUIRED
+        y CDATA #REQUIRED
+        text CDATA #REQUIRED
+        halign (left|center|right) #REQUIRED
+        valign (top|center|bottom) #REQUIRED>

Added: packages/thuban/branches/upstream/current/Resources/XML/thuban-1.0.dtd
===================================================================
--- packages/thuban/branches/upstream/current/Resources/XML/thuban-1.0.dtd	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/XML/thuban-1.0.dtd	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--    thuban-1.0.dtd
+
+    Copyright (C) 2001, 2003 by Intevation GmbH
+    Authors:
+	Jan-Oliver Wagner <jan at intevation.de>
+        Bernhard Herzog <bh at intevation.de>
+
+    This program is free software under the GPL (>=v2)
+    Read the file COPYING coming with Thuban for details.
+
+    $Revision: 1841 $
+    $Source$
+    $Id: thuban-1.0.dtd 1841 2003-10-21 10:49:03Z bh $
+-->
+
+<!-- a session contains zero or more database connections zero or more
+     datasources and and zero or more maps
+
+At some point, the namespace attribute will likely be used by Thuban to
+identify the version of the file format. 
+-->
+
+<!ENTITY % shapesources "fileshapesource | derivedshapesource | dbshapesource">
+<!ENTITY % tables "filetable | jointable">
+<!ELEMENT session ((dbconnection | %shapesources; | %tables; )*, map*)>
+<!ATTLIST session 
+        title CDATA #REQUIRED
+        xmlns CDATA #IMPLIED
+>
+
+
+<!--
+    A db connection represents the connection to a database.
+
+    Currently only connections to postgis databases are supported and
+    thus The dbtype attribute must be "postgis".
+-->
+
+<!ELEMENT dbconnection EMPTY>
+<!ATTLIST dbconnection
+        id     ID    #REQUIRED
+        dbtype CDATA #REQUIRED
+        dbname CDATA #REQUIRED
+        host   CDATA ""
+        port   CDATA ""
+        user   CDATA ""
+>
+
+
+<!-- A dbshapesource represents a table with geometry data in a database
+
+     The dbconn attribute must be the id of a dbconnection element
+     occurring earlier in the document.
+-->
+
+<!ELEMENT dbshapesource EMPTY>
+<!ATTLIST dbshapesource
+        id        ID    #REQUIRED
+        dbconn    IDREF #REQUIRED
+        tablename CDATA #REQUIRED
+>
+
+<!-- 
+    A fileshapesource is a source of shapes and perhaps attribute data
+    read from a file. The filetype attribute must be one of the
+    supported file types. Currently only "shapefile" is supported.
+ -->
+
+<!ELEMENT fileshapesource EMPTY>
+<!ATTLIST fileshapesource
+        id       ID   #REQUIRED
+        filename CDATA #REQUIRED
+        filetype CDATA #REQUIRED
+>
+
+<!--
+     A derivedshapesource is a source of shapes and attribute data
+    derived from another shapesource for the shapes and a table for the
+    attribute data.
+ -->
+
+<!ELEMENT derivedshapesource EMPTY>
+<!ATTLIST derivedshapesource
+        id          ID   #REQUIRED
+        shapesource IDREF #REQUIRED
+        table       IDREF #REQUIRED
+>
+
+
+<!-- a filetable points to the actual file that
+	contains the tabular data.
+
+     The filetype Attribute may be onve of "DBF" or "CSV"
+-->
+<!ELEMENT filetable EMPTY>
+<!ATTLIST filetable 
+        id       ID    #REQUIRED
+        title    CDATA #REQUIRED
+        filename CDATA #REQUIRED
+        filetype CDATA #REQUIRED>
+
+<!-- 
+    A jointable is a table with the result of something equivalent to
+    this SQL Statement:
+
+     SELECT * FROM left JOIN right WHERE left.leftcolumn = right.rightcolumn;
+
+    The attributes left and right must be the ids of two tables defined
+    previously in the XML-Document file. leftcolumn and rightcolumn are 
+    the column names to join on.
+
+    The jointype attribute should be either "INNER" or "LEFT OUTER".
+-->
+<!ELEMENT jointable EMPTY>
+<!ATTLIST jointable
+        id          ID    #REQUIRED
+        title       CDATA #REQUIRED
+        left        IDREF #REQUIRED
+        leftcolumn  CDATA #REQUIRED
+        right       IDREF #REQUIRED
+        rightcolumn CDATA #REQUIRED
+        jointype    CDATA #REQUIRED
+>
+
+<!-- A Map
+
+        A map consists of a number of layers
+	the projection refers to the projection
+	used to display the map. If the projection
+	is missing, geographic coordinates in decimal
+	degrees are assumed.
+-->
+<!ELEMENT map (projection?, (layer | rasterlayer)*, labellayer?)>
+<!ATTLIST map title CDATA #REQUIRED>
+
+<!-- a layer represents a set of geographic objects.
+	pointers to the actual data are stored.
+	The shapestore attributes contains the id of the data store
+        shown in the layer.
+	the projection refers to the projection
+	in which the data are stored. If the projection
+	is missing, geographic coordinates in decimal
+	degrees are assumed. Visibility is assumed true
+    unless otherwise specified.
+-->
+<!ELEMENT layer (projection?, classification?)>
+<!ATTLIST layer title CDATA #REQUIRED>
+<!ATTLIST layer shapestore IDREF #REQUIRED>
+<!ATTLIST layer visible (true|false) "true">
+<!-- the fill and stroke attributes can be either "None" or "#RRGGBB"
+     RGB hex values
+
+     All of fill, stroke and stroke_width may be omitted and default to
+     "None", "#000000" and "1" respectively.
+ -->
+<!ATTLIST layer fill CDATA "None">
+<!ATTLIST layer stroke CDATA "#000000">
+<!ATTLIST layer stroke_width CDATA "1">
+
+
+<!-- a rasterlayer represents an image that has some geographic data
+    associated with it. The filename points to the image used.
+-->
+<!ELEMENT rasterlayer (projection?, classification?)>
+<!ATTLIST rasterlayer 
+        title    CDATA #REQUIRED
+        filename CDATA #REQUIRED
+        visible  (true|false) "true">
+
+
+<!-- Classification data -->
+<!ELEMENT classification (clnull?, clpoint*, clrange*, clcont*)>
+<!ATTLIST classification field CDATA #REQUIRED>
+<!ATTLIST classification field_type CDATA #REQUIRED>
+
+<!ELEMENT clnull (cldata*)>
+<!ELEMENT clpoint (cldata*)>
+<!ELEMENT clrange (cldata*)>
+<!ELEMENT clcont (cldata*)>
+
+<!ATTLIST clnull label CDATA #IMPLIED>
+
+<!ATTLIST clpoint value CDATA #REQUIRED>
+<!ATTLIST clpoint label CDATA #IMPLIED>
+
+<!ATTLIST clrange min CDATA #IMPLIED>
+<!ATTLIST clrange max CDATA #IMPLIED>
+<!ATTLIST clrange range CDATA #IMPLIED>
+<!ATTLIST clrange label CDATA #IMPLIED>
+
+<!ATTLIST clcont rmin CDATA #REQUIRED>
+<!ATTLIST clcont rmax CDATA #REQUIRED>
+<!ATTLIST clcont dmin CDATA #REQUIRED>
+<!ATTLIST clcont dmax CDATA #REQUIRED>
+
+<!-- Visual appearance of the classification 
+
+     the fill and stroke attributes can be either "None" or "#RRGGBB"
+     RGB hex values
+
+     All of fill, stroke and stroke_width may be omitted and default to
+     "None", "#000000" and "1" respectively.
+ -->
+<!ELEMENT cldata EMPTY>
+<!ATTLIST cldata 
+        stroke       CDATA #IMPLIED
+        stroke_width CDATA #IMPLIED
+        fill         CDATA #IMPLIED
+>
+
+
+<!-- a projection has a number of parameters
+-->
+<!ELEMENT projection (parameter*)>
+<!ATTLIST projection 
+        name CDATA "" 
+        epsg CDATA #IMPLIED >
+
+<!-- just a simple parameter consisting of a value
+-->
+<!ELEMENT parameter EMPTY>
+<!ATTLIST parameter value CDATA #REQUIRED>
+
+
+<!-- The label layer contains text labels -->
+<!ELEMENT labellayer (label*) >
+
+<!ELEMENT label EMPTY>
+<!ATTLIST label
+        x CDATA #REQUIRED
+        y CDATA #REQUIRED
+        text CDATA #REQUIRED
+        halign (left|center|right) #REQUIRED
+        valign (top|center|bottom) #REQUIRED>

Added: packages/thuban/branches/upstream/current/Resources/XML/thuban-1.1.dtd
===================================================================
--- packages/thuban/branches/upstream/current/Resources/XML/thuban-1.1.dtd	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/XML/thuban-1.1.dtd	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--    thuban-1.1.dtd
+
+    Copyright (C) 2001, 2003, 2004, 2005 by Intevation GmbH
+    Authors:
+        Jan-Oliver Wagner <jan at intevation.de>
+        Bernhard Herzog <bh at intevation.de>
+
+    This program is free software under the GPL (>=v2)
+    Read the file COPYING coming with Thuban for details.
+
+    $Revision: 2688 $
+    $Source$
+    $Id: thuban-1.1.dtd 2688 2006-06-30 12:27:20Z frank $
+-->
+
+<!-- a session contains zero or more database connections zero or more
+     datasources and and zero or more maps
+
+At some point, the namespace attribute will likely be used by Thuban to
+identify the version of the file format. 
+-->
+
+<!ENTITY % shapesources "fileshapesource | derivedshapesource | dbshapesource">
+<!ENTITY % tables "filetable | jointable">
+<!ELEMENT session ((dbconnection | %shapesources; | %tables; )*, map*)>
+<!ATTLIST session 
+        title CDATA #REQUIRED
+        xmlns CDATA #IMPLIED
+>
+
+
+<!--
+    A db connection represents the connection to a database.
+
+    Currently only connections to postgis databases are supported and
+    thus The dbtype attribute must be "postgis".
+-->
+
+<!ELEMENT dbconnection EMPTY>
+<!ATTLIST dbconnection
+        id     ID    #REQUIRED
+        dbtype CDATA #REQUIRED
+        dbname CDATA #REQUIRED
+        host   CDATA ""
+        port   CDATA ""
+        user   CDATA ""
+>
+
+
+<!-- A dbshapesource represents a table with geometry data in a database
+
+     The dbconn attribute must be the id of a dbconnection element
+     occurring earlier in the document.
+-->
+
+<!ELEMENT dbshapesource EMPTY>
+<!ATTLIST dbshapesource
+        id        ID    #REQUIRED
+        dbconn    IDREF #REQUIRED
+        tablename CDATA #REQUIRED
+        id_column CDATA #REQUIRED
+        geometry_column CDATA #REQUIRED
+>
+
+<!-- 
+    A fileshapesource is a source of shapes and perhaps attribute data
+    read from a file. The filetype attribute must be one of the
+    supported file types. Currently only "shapefile" is supported.
+ -->
+
+<!ELEMENT fileshapesource EMPTY>
+<!ATTLIST fileshapesource
+        id       ID   #REQUIRED
+        filename CDATA #REQUIRED
+        filetype CDATA #REQUIRED
+>
+
+<!--
+     A derivedshapesource is a source of shapes and attribute data
+    derived from another shapesource for the shapes and a table for the
+    attribute data.
+ -->
+
+<!ELEMENT derivedshapesource EMPTY>
+<!ATTLIST derivedshapesource
+        id          ID   #REQUIRED
+        shapesource IDREF #REQUIRED
+        table       IDREF #REQUIRED
+>
+
+
+<!-- a filetable points to the actual file that
+	contains the tabular data.
+
+     The filetype Attribute may be onve of "DBF" or "CSV"
+-->
+<!ELEMENT filetable EMPTY>
+<!ATTLIST filetable 
+        id       ID    #REQUIRED
+        title    CDATA #REQUIRED
+        filename CDATA #REQUIRED
+        filetype CDATA #REQUIRED>
+
+<!-- 
+    A jointable is a table with the result of something equivalent to
+    this SQL Statement:
+
+     SELECT * FROM left JOIN right WHERE left.leftcolumn = right.rightcolumn;
+
+    The attributes left and right must be the ids of two tables defined
+    previously in the XML-Document file. leftcolumn and rightcolumn are 
+    the column names to join on.
+
+    The jointype attribute should be either "INNER" or "LEFT OUTER".
+-->
+<!ELEMENT jointable EMPTY>
+<!ATTLIST jointable
+        id          ID    #REQUIRED
+        title       CDATA #REQUIRED
+        left        IDREF #REQUIRED
+        leftcolumn  CDATA #REQUIRED
+        right       IDREF #REQUIRED
+        rightcolumn CDATA #REQUIRED
+        jointype    CDATA #REQUIRED
+>
+
+<!-- A Map
+
+        A map consists of a number of layers
+	the projection refers to the projection
+	used to display the map. If the projection
+	is missing, geographic coordinates in decimal
+	degrees are assumed.
+-->
+<!ELEMENT map (projection?, (layer | rasterlayer)*, labellayer?)>
+<!ATTLIST map title CDATA #REQUIRED>
+
+<!-- a layer represents a set of geographic objects.
+	pointers to the actual data are stored.
+	The shapestore attributes contains the id of the data store
+        shown in the layer.
+	the projection refers to the projection
+	in which the data are stored. If the projection
+	is missing, geographic coordinates in decimal
+	degrees are assumed. Visibility is assumed true
+    unless otherwise specified.
+-->
+<!ELEMENT layer (projection?, classification?)>
+<!ATTLIST layer title CDATA #REQUIRED>
+<!ATTLIST layer shapestore IDREF #REQUIRED>
+<!ATTLIST layer visible (true|false) "true">
+<!-- the fill and stroke attributes can be either "None" or "#RRGGBB"
+     RGB hex values
+
+     All of fill, stroke, stroke_width and size may be omitted and default
+     to "None", "#000000", "1" and "5" respectively.
+ -->
+<!ATTLIST layer fill CDATA "None">
+<!ATTLIST layer stroke CDATA "#000000">
+<!ATTLIST layer stroke_width CDATA "1">
+<!ATTLIST layer size CDATA "5">
+
+
+<!-- a rasterlayer represents an image that has some geographic data
+    associated with it. The filename points to the image used.
+
+    The masktype should be one of "none", "bit" or "alpha".  
+    The opacity is the opacity as a decimal floating point number in the
+    range 0.0 ... 1.0
+-->
+<!ELEMENT rasterlayer (projection?, classification?)>
+<!ATTLIST rasterlayer 
+        title    CDATA #REQUIRED
+        filename CDATA #REQUIRED
+        opacity CDATA #IMPLIED
+        masktype CDATA #IMPLIED
+        visible  (true|false) "true">
+
+
+<!-- Classification data -->
+<!ELEMENT classification (clnull?, clpoint*, clrange*, clpattern*, clcont*)>
+<!ATTLIST classification field CDATA>
+<!ATTLIST classification field_type CDATA>
+
+<!ELEMENT clnull (cldata*)>
+<!ELEMENT clpoint (cldata*)>
+<!ELEMENT clrange (cldata*)>
+<!ELEMENT clpattern (cldata*)>
+<!ELEMENT clcont (cldata*)>
+
+<!ATTLIST clnull label CDATA #IMPLIED>
+
+<!ATTLIST clpoint value CDATA #REQUIRED>
+<!ATTLIST clpoint label CDATA #IMPLIED>
+
+<!ATTLIST clrange min CDATA #IMPLIED>
+<!ATTLIST clrange max CDATA #IMPLIED>
+<!ATTLIST clrange range CDATA #IMPLIED>
+<!ATTLIST clrange label CDATA #IMPLIED>
+
+<!ATTLIST clpattern pattern CDATA #REQUIRED>
+<!ATTLIST clpattern label CDATA #IMPLIED>
+
+<!ATTLIST clcont rmin CDATA #REQUIRED>
+<!ATTLIST clcont rmax CDATA #REQUIRED>
+<!ATTLIST clcont dmin CDATA #REQUIRED>
+<!ATTLIST clcont dmax CDATA #REQUIRED>
+
+<!-- Visual appearance of the classification 
+
+     the fill and stroke attributes can be either "None" or "#RRGGBB"
+     RGB hex values
+
+     TODO: Actually, 'size' is only sensible for points. But adding it to
+     clpoint would not be enough since the 'size' must also be available
+     for the clnull. And clnull again is applied for lines and polygons.
+     So, at some later point, maybe with introducing symbols, this
+     has to be improved.
+
+     All of fill, stroke, stroke_width and size may be omitted and default to
+     "None", "#000000", "1" and "5" respectively.
+ -->
+<!ELEMENT cldata EMPTY>
+<!ATTLIST cldata 
+        stroke       CDATA #IMPLIED
+        stroke_width CDATA #IMPLIED
+        fill         CDATA #IMPLIED
+        size         CDATA #IMPLIED
+>
+
+
+<!-- a projection has a number of parameters
+-->
+<!ELEMENT projection (parameter*)>
+<!ATTLIST projection 
+        name CDATA "" 
+        epsg CDATA #IMPLIED >
+
+<!-- just a simple parameter consisting of a value
+-->
+<!ELEMENT parameter EMPTY>
+<!ATTLIST parameter value CDATA #REQUIRED>
+
+
+<!-- The label layer contains text labels -->
+<!ELEMENT labellayer (label*) >
+
+<!ELEMENT label EMPTY>
+<!ATTLIST label
+        x CDATA #REQUIRED
+        y CDATA #REQUIRED
+        text CDATA #REQUIRED
+        halign (left|center|right) #REQUIRED
+        valign (top|center|bottom) #REQUIRED>

Added: packages/thuban/branches/upstream/current/Resources/XML/thuban.dtd
===================================================================
--- packages/thuban/branches/upstream/current/Resources/XML/thuban.dtd	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Resources/XML/thuban.dtd	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--    thuban.dtd
+
+    Copyright (C) 2001, 2003 by Intevation GmbH
+    Authors:
+	Jan-Oliver Wagner <jan at intevation.de>
+
+    This program is free software under the GPL (>=v2)
+    Read the file COPYING coming with Thuban for details.
+
+    This DTD covers .thuban files for Thuban versions up to 0.2 and most
+    of the .thuban files generated by development/CVS versions of Thuban
+    between 0.2 and 0.8.
+ -->
+
+<!-- a session contains a number of maps and tables
+-->
+<!ELEMENT session (map*, table*)>
+<!ATTLIST session title CDATA #REQUIRED>
+
+<!-- a map consists of a number of layers
+	the projection refers to the projection
+	used for discplaing the map. If the projection
+	is missing, geographic coordinates in decimal
+	degrees are assumed.
+-->
+<!ELEMENT map (projection?, (layer | rasterlayer)*, labellayer?)>
+<!ATTLIST map title CDATA #REQUIRED>
+
+<!-- a layer represents a set of geographic objects.
+	pointers to the actual data are stored.
+	currently only a filename points to the data.
+	the projection refers to the projection
+	in which the data are stored. If the projection
+	is missing, geographic coordinates in decimal
+	degrees are assumed. Visibility is assumed true
+    unless otherwise specified.
+-->
+<!ELEMENT layer (projection?, classification?)>
+<!ATTLIST layer title CDATA #REQUIRED>
+<!ATTLIST layer filename CDATA #REQUIRED>
+<!ATTLIST layer visible (true|false) "true">
+
+<!-- the fill and stroke attributes can be either "None" or "#RRGGBB"
+     RGB hex values
+
+     All of fill, stroke and stroke_width may be omitted and default to
+     "None", "#000000" and "1" respectively.
+ -->
+<!ATTLIST layer fill CDATA "None">
+<!ATTLIST layer stroke CDATA "#000000">
+<!ATTLIST layer stroke_width CDATA "1">
+
+<!-- a rasterlayer represents an image that has some geographic data
+    associated with it. The filename points to the image used.
+-->
+<!ELEMENT rasterlayer (projection?, classification?)>
+<!ATTLIST rasterlayer title CDATA #REQUIRED>
+<!ATTLIST rasterlayer filename CDATA #REQUIRED>
+<!ATTLIST rasterlayer visible (true|false) "true">
+
+<!-- Classification data -->
+<!ELEMENT classification (clnull?, (clpoint | clrange | clcont)*)>
+<!ATTLIST classification field CDATA #REQUIRED>
+<!ATTLIST classification field_type CDATA #REQUIRED>
+
+<!ELEMENT clnull (cldata*)>
+<!ELEMENT clpoint (cldata*)>
+<!ELEMENT clrange (cldata*)>
+<!ELEMENT clcont (cldata*)>
+
+<!ATTLIST clnull label CDATA #IMPLIED>
+
+<!ATTLIST clpoint value CDATA #REQUIRED>
+<!ATTLIST clpoint label CDATA #IMPLIED>
+
+<!ATTLIST clrange min CDATA #IMPLIED>
+<!ATTLIST clrange max CDATA #IMPLIED>
+<!ATTLIST clrange range CDATA #IMPLIED>
+<!ATTLIST clrange label CDATA #IMPLIED>
+
+<!ATTLIST clcont rmin CDATA #REQUIRED>
+<!ATTLIST clcont rmax CDATA #REQUIRED>
+<!ATTLIST clcont dmin CDATA #REQUIRED>
+<!ATTLIST clcont dmax CDATA #REQUIRED>
+
+<!ELEMENT cldata EMPTY>
+<!ATTLIST cldata 
+        stroke       CDATA #IMPLIED
+        stroke_width CDATA #IMPLIED
+        fill         CDATA #IMPLIED
+>
+
+<!-- a table points to the actual file that
+	contains the tabular data.
+-->
+<!ELEMENT table EMPTY>
+<!ATTLIST table title CDATA #REQUIRED>
+<!ATTLIST table filename CDATA #REQUIRED>
+
+<!-- a projection has a number of parameters
+-->
+<!ELEMENT projection (parameter*)>
+<!ATTLIST projection
+        name CDATA #IMPLIED >
+
+<!-- just a simple parameter consisting of a value
+-->
+<!ELEMENT parameter EMPTY>
+<!ATTLIST parameter value CDATA #REQUIRED>
+
+
+<!-- The label layer contains text labels -->
+<!ELEMENT labellayer (label*) >
+
+<!ELEMENT label EMPTY>
+<!ATTLIST label
+        x CDATA #REQUIRED
+        y CDATA #REQUIRED
+        text CDATA #REQUIRED
+        halign (left|center|right) #REQUIRED
+        valign (top|center|bottom) #REQUIRED>

Added: packages/thuban/branches/upstream/current/Thuban/Lib/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Lib/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Lib/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,6 @@
+# Copyright (c) 2001 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.

Added: packages/thuban/branches/upstream/current/Thuban/Lib/classmapper.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Lib/classmapper.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Lib/classmapper.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,81 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+The provided class maintains a mapping between classes and objects.
+Instances of the class are used as keys, not classes, though.
+
+Usually layer classes and their instances are used in combination with
+layer property dialog classes in order to utilise the proper dialog
+for a given layer instance.
+
+"""
+
+__version__ = "$Revision: 2299 $"
+# $Source$
+# $Id: classmapper.py 2299 2004-07-26 16:08:07Z joey $
+
+
+class ClassMapper:
+    """
+    Thuban class to implement a mapping of classes and objects,
+    usually also classes.
+    """
+
+    mapping = None
+
+
+    def __init__(self):
+        """
+        Initialises a mapping.
+        """
+
+        self.mapping = []
+
+
+    def add(self, key_class, obj):
+        """
+        Register an object with a class.
+
+        This method adds the provided pair (key_class,obj) to the
+        internal list.  Subsequently instances of key_class are used
+        to retrieved the stored object.
+        """
+
+        self.mapping.append((key_class, obj))
+
+
+    def get(self, instance):
+        """
+        Retrieve a stored object corresponding to the provided class
+        instance.
+        """
+
+        for key_class, obj in self.mapping:
+            if isinstance(instance, key_class):
+                return obj
+        return None
+
+
+    def has(self, instance):
+        """
+        Determine if the ClassMapper contains an object corresponding
+        to the provided instance
+        """
+
+        return self.get(instance) is not None

Added: packages/thuban/branches/upstream/current/Thuban/Lib/connector.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Lib/connector.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Lib/connector.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,181 @@
+# This module was copied almost verbatim from Sketch. The only change is
+# the base class of ConnectorError which was a Sketch specific exception
+# class. 
+
+# Sketch - A Python-based interactive drawing program
+# Copyright (C) 1997, 1998, 2000, 2001, 2003 by Bernhard Herzog
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+__version__ = "$Revision: 1952 $"
+
+#
+#       The Connector
+#
+
+import sys
+from types import MethodType
+
+from Thuban import _
+
+class ConnectorError(Exception):
+    pass
+
+class Connector:
+
+    def __init__(self):
+        self.connections = {}
+
+    def Connect(self, object, channel, function, args):
+        idx = id(object)
+        if self.connections.has_key(idx):
+            channels = self.connections[idx]
+        else:
+            channels = self.connections[idx] = {}
+
+        if channels.has_key(channel):
+            receivers = channels[channel]
+        else:
+            receivers = channels[channel] = []
+
+        info = (function, args)
+        try:
+            receivers.remove(info)
+        except ValueError:
+            pass
+        receivers.append(info)
+
+    def Disconnect(self, object, channel, function, args):
+        try:
+            receivers = self.connections[id(object)][channel]
+        except KeyError:
+            raise ConnectorError, \
+                  _('no receivers for channel %s of %s') % (channel, object)
+        try:
+            receivers.remove((function, args))
+        except ValueError:
+            raise ConnectorError,\
+            _('receiver %s%s is not connected to channel %s of %s') \
+            % (function, args, channel, object)
+
+        if not receivers:
+            # the list of receivers is empty now, remove the channel
+            channels = self.connections[id(object)]
+            del channels[channel]
+            if not channels:
+                # the object has no more channels
+                del self.connections[id(object)]
+
+    def Issue(self, object, channel, *args):
+        #print object, channel, args
+        try:
+            receivers = self.connections[id(object)][channel]
+        except KeyError:
+            return
+        # Iterate over a copy of receivers because the receivers might
+        # unsubscribe themselves when receiving a message and Disconnect
+        # would modify receivers in place while we're iterating over it.
+        for func, fargs in receivers[:]:
+            try:
+                apply(func, args + fargs)
+            except:
+                sys.stderr.write(_("Warning: %s.%s: %s%s\n")
+                                 % (object, channel, func, fargs))
+                import traceback
+                traceback.print_exc()
+
+    def RemovePublisher(self, object):
+        i = id(object)
+        if self.connections.has_key(i):
+            del self.connections[i]
+        # don't use try: del ... ; except KeyError here. That would create a
+        # new reference of object in a traceback object and this method should
+        # be callable from a __del__ method (at least for versions prior
+        # Python 1.5)
+
+    def HasSubscribers(self, object):
+        return self.connections.has_key(id(object))
+
+    def print_connections(self):
+        # for debugging
+        for id, channels in self.connections.items():
+            for name, subscribers in channels.items():
+                print hex(id), name
+                for func, args in subscribers:
+                    if type(func) == MethodType:
+                        print _('\tmethod %s of %s') % (func.im_func.func_name,
+                                                        func.im_self)
+                    else:
+                        print '\t', func
+
+
+
+_the_connector = Connector()
+
+Connect = _the_connector.Connect
+Issue = _the_connector.Issue
+RemovePublisher = _the_connector.RemovePublisher
+Disconnect = _the_connector.Disconnect
+def Subscribe(channel, function, *args):
+    return Connect(None, channel, function, args)
+
+
+class Publisher:
+
+    # Flag indicating whether the publisher instance was destroyed.
+    _was_destroyed = False
+
+    def __del__(self):
+        # the new finalization code in 1.5.1 might bind RemovePublisher
+        # to None before all objects derived from Publisher are deleted...
+        if RemovePublisher is not None:
+            RemovePublisher(self)
+
+    def Subscribe(self, channel, func, *args):
+        Connect(self, channel, func, args)
+
+    def Unsubscribe(self, channel, func, *args):
+        """Unsubscribe from the channel.
+
+        If the publisher's Destroy method has been called already, do
+        nothing, because the subscriptions will already have been
+        removed in Destroy and trying to disconnect it here will lead to
+        exceptions.
+        """
+        if not self._was_destroyed:
+            Disconnect(self, channel, func, args)
+
+    def issue(self, channel, *args):
+        apply(Issue, (self, channel,) + args)
+
+    def Destroy(self):
+        """Remove all subscriptions of messages sent by self."""
+        RemovePublisher(self)
+        self._was_destroyed = True
+
+
+class Conduit(Publisher):
+
+    def _do_forward(self, *args, **kw):
+        self.issue(args[-1], *args[:-1], **kw)
+
+    def subscribe_forwarding(self, channel, obj):
+        if obj is not None:
+            obj.Subscribe(channel, self._do_forward, channel)
+
+    def unsubscribe_forwarding(self, channel, obj):
+        if obj is not None:
+            obj.Unsubscribe(channel, self._do_forward, channel)
+

Added: packages/thuban/branches/upstream/current/Thuban/Lib/fileutil.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Lib/fileutil.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Lib/fileutil.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,222 @@
+# Copyright (c) 2001, 2002 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Functions to deal with filenames
+"""
+
+__version__ = "$Revision: 1885 $"
+
+import os
+import os.path
+from tempfile import mktemp
+
+from string import join
+
+from Thuban import _
+
+def relative_filename_common(dir, absname, sep):
+    """Return a filename relative to dir for the absolute file name absname.
+    This is part the posix and nt versions have in common. Both dir and
+    absname are assumed to be normalized (as done with os.normpath)
+    absolute filenames without drive letters. sep is the platform
+    specific directory separator.
+    """
+
+    # split the filenames into their components. remove the first item
+    # since it will be always empty because both names are absolute.
+    dir_parts = dir.split(sep)[1:]
+    absname_parts = absname.split(sep)[1:]
+
+    # count the number of common parts at the start of dir_parts and
+    # absname_parts
+    max_common = min(len(dir_parts), len(absname_parts))
+    common = 0
+    while common < max_common and dir_parts[common] == absname_parts[common]:
+        common = common + 1
+
+    # If the common part is the root directory, return absname
+    if common == 0:
+        return absname
+
+    # for each directory under the common part prepend a '..'.
+    rel_parts = (len(dir_parts) - common) * ['..'] + absname_parts[common:]
+    return join(rel_parts, sep)
+    
+
+def relative_filename_posix(dir, absname):
+    """Return a filename relative to dir for the absolute file name absname.
+
+    If absname is already a relative filename, return it unchanged. If
+    the common directory of dir and absname is /, return absname
+    unchanged. If dir is not an absolute name, raise TypeError.
+
+    This is the posix specific version of relative_filename.
+
+    Example:
+    >>> from fileutil import relative_filename_posix
+    >>> relative_filename_posix("/usr/local/lib/", "/usr/local/lib/python")
+    'python'
+    >>> relative_filename_posix("/usr/local/lib/", "/usr/local/bin/python")
+    '../bin/python'
+    >>> relative_filename_posix("/usr/local/lib/", "/usr/bin/python")
+    '../../bin/python'
+    >>> relative_filename_posix("/usr/local/lib/", "/var/spool/mail")
+    '/var/spool/mail'
+    >>> relative_filename_posix("/home/", "xyzzy")
+    'xyzzy'
+    >>> relative_filename_posix("home/", "/xyzzy")
+    Traceback (most recent call last):
+      File "<stdin>", line 1, in ?
+      File "fileutil.py", line 42, in relative_filename_posix
+        raise TypeError("first argument must be an absolute filename")
+    TypeError: first argument must be an absolute filename
+    """
+    # for posix, the common part does exactly what we need, except for
+    # the special cases and input checking. Import posixpath explicitly
+    # for that to faciliate testing
+    import posixpath
+    if not posixpath.isabs(absname):
+        return absname
+
+    if not posixpath.isabs(dir):
+        raise TypeError(_("first argument must be an absolute filename"))
+
+    dir = posixpath.normpath(dir)
+    absname = posixpath.normpath(absname)
+
+    return relative_filename_common(dir, absname, "/")
+
+def relative_filename_nt(dir, absname):
+    r"""Return a filename relative to dir for the absolute file name absname.
+
+    If absname is already a relative filename or if dir and absname are
+    on different drives, return absname. If the common directory of dir
+    and absname is the drive's root directory, return absname. If dir is
+    not an absolute name or either name doesn't have a drive letter,
+    raise TypeError.
+
+    This is the nt specific version of relative_filename.
+
+    Example:
+    >>> from fileutil import relative_filename_nt
+    >>> relative_filename_nt(r"C:\Programme\Python", r"C:\Programme\Thuban")
+    '..\\Thuban'
+    >>> relative_filename_nt(r"C:\Programme\Python", r"D:\Programme\Thuban")
+    'D:\\Programme\\Thuban'
+    >>> relative_filename_nt(r"C:\Programme\Python", r"C:Programme")
+    'C:Programme'
+    >>> relative_filename_nt(r"C:Programme\Python", r"C:Programme")
+    Traceback (most recent call last):
+      File "<stdin>", line 1, in ?
+      File "fileutil.py", line 123, in relative_filename_nt
+        raise TypeError("first argument must be an absolute filename")
+    TypeError: first argument must be an absolute filename
+    >>> relative_filename_nt(r"\Programme\Python", r"\Programme")
+    Traceback (most recent call last):
+      File "<stdin>", line 1, in ?
+      File "fileutil.py", line 120, in relative_filename_nt
+        raise TypeError("Both parameters must have a drive letter")
+    TypeError: Both parameters must have a drive letter
+    """
+    # first check the parameters. Imort ntpath directly to facilitate
+    # testing on non-nt systems.
+    import ntpath
+
+    dir = ntpath.normpath(dir)
+    absname = ntpath.normpath(absname)
+
+    dir_drive, dir_rest = ntpath.splitdrive(dir)
+    absname_drive, absname_rest = ntpath.splitdrive(absname)
+    #print dir_drive, dir_rest
+    #print absname_drive, absname_rest
+    if not dir_drive or not absname_drive:
+        raise TypeError(_("Both parameters must have a drive letter"))
+
+    if not ntpath.isabs(dir_rest):
+        raise TypeError(_("first argument must be an absolute filename"))
+
+    # handle some special cases
+    if not ntpath.isabs(absname_rest):
+        return absname
+
+    if dir_drive != absname_drive:
+        return absname
+
+    # Now both dir_rest and absname_rest are absolute filenames without
+    # drive letter. We can now use the common part to determine the
+    # relative name
+    return relative_filename_common(dir_rest, absname_rest, "\\")
+
+def get_application_dir():
+    """Determine the path to the .thuban directory. Create the directory
+    if it doesn't exist.
+
+    Under posix systems use the os.expanduser() method.
+    Under Win32 try to read the "Explorer/Shell Folders/" value "AppData".
+    """
+
+    if os.name == 'posix':
+        dir = os.path.expanduser("~/.thuban")
+        if not os.path.isdir(dir):
+           os.mkdir(dir)
+        return dir
+    elif os.name == 'nt':
+        regkey = 1
+        try:
+            import _winreg as wreg
+        except ImportError:
+            regkey = 0
+
+        if regkey:
+            try:
+                key = wreg.OpenKey(wreg.HKEY_CURRENT_USER, 
+                  "Software\\Microsoft\\Windows\\CurrentVersion\\"\
+                  "Explorer\\Shell Folders")
+                dir = wreg.QueryValueEx(key, "AppData")[0]
+                dir = os.path.join(dir, "thuban")
+            except:
+                regkey = 0
+
+        if not regkey:
+            # The fallback. This should result in something like the 
+            # user directory ...
+            guess = os.path.dirname(
+                                os.path.dirname(os.path.dirname(mktemp()))
+                            )
+            dir = os.path.join(guess, "thuban")
+        if not os.path.isdir(dir):
+           os.mkdir(dir)
+
+        return dir
+
+    else:
+        raise RuntimeError(_("No implementation of get_application_dir"
+                       " available for platform") + os.name)
+
+# bind the appropriate version of relative_filename for the platform
+# we're currently running on.
+if os.name == "posix":
+    relative_filename = relative_filename_posix
+elif os.name == "nt":
+    relative_filename = relative_filename_nt
+else:
+    raise RuntimeError(_("No implementation of relative_filename"
+                       " available for platform") + os.name)
+
+__test__ = {"relative_filename_posix": relative_filename_posix,
+            "relative_filename_nt": relative_filename_nt}
+
+# if run as a script, run doctest
+def _test():
+    import doctest, fileutil
+    # Pass an isprivate function that always returns true so that only
+    # items in __test__ are tested
+    return doctest.testmod(fileutil, isprivate = lambda *args: 1)
+    
+if __name__ == "__main__":
+    _test()

Added: packages/thuban/branches/upstream/current/Thuban/Lib/version.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Lib/version.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Lib/version.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,42 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Version number handling"""
+
+__version__ = "$Revision: 2011 $"
+# $Source$
+# $Id: version.py 2011 2003-12-03 09:46:27Z bh $
+
+
+import re
+
+rx_version = re.compile("[0-9]+(\\.[0-9]+)*")
+
+def make_tuple(s):
+    """Return a tuple version of the version number string s
+
+    The version string must start with a sequence of decimal integers
+    separated by dots. The return value is a tuple of up to three
+    integers, one for each number at the beginnin of the version string.
+
+    If the string does not start with a number return None
+
+    Examples:
+    >>> import version
+    >>> version.make_tuple('1.2')
+    (1, 2)
+    >>> version.make_tuple('2.4.0.7')
+    (2, 4, 0)
+    >>> version.make_tuple('1.2+cvs.20031111')
+    (1, 2)
+    >>> version.make_tuple('foo')
+    >>>
+    """
+    match = rx_version.match(s)
+    if match:
+        return tuple(map(int, match.group(0).split(".")[:3]))
+

Added: packages/thuban/branches/upstream/current/Thuban/Model/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,6 @@
+# Copyright (c) 2001 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.

Added: packages/thuban/branches/upstream/current/Thuban/Model/base.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/base.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/base.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,77 @@
+# Copyright (c) 2001, 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Various base classes that did not fit elsewhere.
+"""
+
+__version__ = "$Revision: 2413 $"
+
+from Thuban.Lib.connector import Publisher
+
+from messages import TITLE_CHANGED, CHANGED
+
+class TitledObject:
+
+    """Mix-in class for objects that have titles"""
+
+    def __init__(self, title):
+        self.title = title
+
+    def Title(self):
+        return self.title
+
+    def SetTitle(self, title):
+        self.title = title
+
+        # FIXME: The TitledObject is almost always used in conjunction
+        # with Modifiable (the only exceptions currently are the
+        # tables). We should reall derive TitledObject from modifiable
+        # (would be good for the tables too) but that's taking things a
+        # bit far at the moment.
+        if hasattr(self, 'changed'):
+            self.changed(TITLE_CHANGED, self)
+
+class Modifiable(Publisher):
+
+    """Class for objects maintaining a modified flag."""
+
+    def __init__(self):
+        self.modified = 0
+
+    def WasModified(self):
+        """Return true if the layer was modified"""
+        return self.modified
+
+    def UnsetModified(self):
+        """Unset the modified flag.
+
+        If the modified flag is changed from set to unset by the call,
+        issue a CHANGED message.
+
+        The modified flag itself is part of the state of the object so
+        some other objects such as a field in the status bar indication
+        whether e.g. the session has changed might be interested in
+        being notified when this flag has changed.
+        """
+        was_modified = self.modified
+        self.modified = 0
+        if was_modified:
+            self.issue(CHANGED)
+
+    def changed(self, channel = None, *args):
+        """Set the modified flag and optionally issue a message
+
+        The message is issued on the channel given by channel with args
+        as the arguments. If channel is None issue no message.
+
+        Subclasses should call this method whenever anything has
+        changed.
+        """
+        self.modified = 1
+        if channel is not None:
+            self.issue(channel, *args)

Added: packages/thuban/branches/upstream/current/Thuban/Model/classgen.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/classgen.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/classgen.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,481 @@
+# -*- encoding: iso-8859-1 -*-
+#
+# Copyright (c) 2003-2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2004)
+# Bernhard Herzog <bh at intevation.de> (2003)
+# Thomas Köster <tkoester at intevation.de> (2003)
+# Jonathan Coles <jonathan at intevation.de> (2003)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Functions to generate Classifications
+"""
+
+__version__ = "$Revision: 2441 $"
+# $Source$
+# $Id: classgen.py 2441 2004-12-09 10:50:34Z joey $
+
+import operator
+
+from color import Color, Transparent
+from range import Range
+from classification import Classification, ClassGroupSingleton, \
+    ClassGroupRange, ClassGroupProperties
+
+def generate_singletons(_list, ramp):
+    """Generate a new classification consisting solely of singletons.
+
+    The resulting classification will consist of one group for each
+    item in _list whose properties ramp between 'prop1' and 'prop2'. 
+
+    _list -- a list of values for each singleton
+
+    ramp -- an object which implements the CustomRamp interface
+    """
+
+    clazz = Classification()
+
+    i = 0
+    maxValue = float(len(_list) - 1)
+    if maxValue < 1: maxValue = 1
+
+    for value in _list:
+        prop = ramp.GetProperties(i / maxValue)
+        clazz.AppendGroup(ClassGroupSingleton(value, prop))
+        i += 1
+
+    return clazz
+
+def generate_uniform_distribution(min, max, numGroups, ramp, intStep = False):
+    """Generate a classification with numGroups range groups
+    each with the same interval.
+
+    intStep -- force the calculated stepping to an integer.
+               Useful if the values are integers but the
+               number of groups specified doesn't evenly
+               divide (max - min).
+    """
+
+    clazz = Classification()
+
+    cur_min = min
+
+    end = "["
+    maxValue = float(numGroups - 1)
+    if maxValue < 1: maxValue = 1
+
+    for i in range(1, numGroups + 1):
+
+        prop = ramp.GetProperties(float(i-1) / maxValue)
+
+        if intStep:
+            cur_max = min + int(round((i * (max - min + 1)) / float(numGroups)))
+        else:
+            cur_max = min + (i * (max - min)) / float(numGroups)
+
+        if i == numGroups:
+            cur_max = max
+            end = "]"
+
+        if cur_min == cur_max:
+            _range = Range(("[", cur_min, cur_max, "]"))
+        else:
+            _range = Range(("[", cur_min, cur_max, end))
+
+        clazz.AppendGroup(ClassGroupRange(_range, prop))
+
+        cur_min = cur_max
+
+    return clazz
+
+def generate_quantiles(_list, percents, ramp, _range):
+    """Generates a Classification which has groups of ranges that
+    represent quantiles of _list at the percentages given in percents.
+    Only the values that fall within _range are considered. 
+
+    Returns a tuple (adjusted, Classification) where adjusted is
+    True if the Classification does not exactly represent the given
+    range, or if the Classification is empty.
+
+    _list -- a sort list of values
+
+    percents -- a sorted list of floats in the range 0.0-1.0 which
+                represent the upper bound of each quantile. the
+                union of all percentiles should be the entire 
+                range from 0.0-1.0
+
+    ramp -- an object which implements the CustomRamp interface
+
+    _range -- a Range object
+
+    Raises a Value Error if 'percents' has fewer than two items, or
+    does not cover the entire range.
+    """
+
+    clazz = Classification()
+    quantiles = calculate_quantiles(_list, percents, _range)
+    adjusted = True
+
+    if quantiles is not None:
+
+        numGroups = len(quantiles[3])
+
+        if numGroups != 0:
+
+            adjusted = quantiles[0]
+
+            start, min, endMax, right = _range.GetRange()
+
+            oldp = 0
+            i = 1
+            end = "]"
+
+            maxValue = float(numGroups - 1)
+            if maxValue < 1: maxValue = 1
+            for (q, p) in quantiles[3]: 
+
+                prop = ramp.GetProperties(float(i-1) / maxValue)
+
+                if i == numGroups:
+                    max = endMax
+                    end = right
+                else:
+                    max = _list[q]
+
+                group = ClassGroupRange(Range((start, min, max, end)), prop)
+
+                group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2), 
+                                                round(p*100, 2)))
+                oldp = p
+                start = "]"
+                min = max
+                clazz.AppendGroup(group)
+                i += 1
+
+    return (adjusted, clazz)
+
+
+def calculate_quantiles(_list, percents, _range):
+    """Calculate quantiles for the given _list of percents from the
+    sorted list of values that are in range.
+
+    This may not actually generate len(percents) quantiles if
+    many of the values that fall on quantile borders are the same.
+
+    Returns a tuple of the form: 
+        (adjusted, minIndex, maxIndex, [quantile_list])
+
+    where adjusted is True if the the quantile percentages differ from
+    those supplied, minIndex is the index into _list where the 
+    minimum value used is located, maxIndex is the index into _list
+    where the maximum value used is located, and quantile_list is a 
+    list of tuples of the form: (list_index, quantile_percentage)
+
+    Returns None, if no quantiles could be generated based on the
+    given range or input list.
+
+    _list -- a sort list of values
+
+    percents -- a sorted list of floats in the range 0.0-1.0 which
+                represent the upper bound of each quantile. the
+                union of all percentiles should be the entire 
+                range from 0.0-1.0
+
+    _range -- a Range object
+
+    Raises a Value Error if 'percents' has fewer than two items, or
+    does not cover the entire range.
+    """
+
+    quantiles = []
+    adjusted = False
+
+    if len(percents) <= 1:
+        raise ValueError("percents parameter must have more than one item")
+
+    if percents[-1] != 1.0:
+        raise ValueError("percents does not cover the entire range")
+
+    #
+    # find what part of the _list range covers
+    #
+    minIndex = -1
+    maxIndex = -2
+    for i in xrange(0, len(_list), 1):
+        if operator.contains(_range, _list[i]):
+            minIndex = i
+            break
+
+    for i in xrange(len(_list)-1, -1, -1):
+        if operator.contains(_range, _list[i]):
+            maxIndex = i
+            break
+
+    numValues = maxIndex - minIndex + 1
+
+    if numValues > 0:
+
+        #
+        # build a list of unique indices into list of where each
+        # quantile *should* be. set adjusted if the resulting
+        # indices are different
+        #
+        quantiles = {}
+        for p in percents:
+            index = min(minIndex + int(p*numValues)-1, maxIndex)
+
+            adjusted = adjusted \
+                or quantiles.has_key(index) \
+                or ((index - minIndex + 1) / float(numValues)) != p
+
+            quantiles[index] = 0
+
+        quantiles = quantiles.keys()
+        quantiles.sort()
+
+        #
+        # the current quantile index must be strictly greater than
+        # the lowerBound
+        #
+        lowerBound = minIndex - 1
+
+        for qindex in xrange(len(quantiles)):
+            if lowerBound >= maxIndex:
+                # discard higher quantiles
+                quantiles = quantiles[:qindex]
+                break
+
+            # lowerBound + 1 is always a valid index
+
+            #
+            # bump up the current quantile index to be a usable index
+            # if it currently falls below the lowerBound
+            #
+            if quantiles[qindex] <= lowerBound:
+                quantiles[qindex] = lowerBound + 1
+
+            listIndex = quantiles[qindex]
+            value = _list[listIndex]
+
+            #
+            # look for similar values around the quantile index
+            #
+            lindex = listIndex - 1
+            while lindex > lowerBound and value == _list[lindex]:
+                lindex -= 1
+            lcount = (listIndex - 1) - lindex
+
+            rindex = listIndex + 1
+            while rindex < maxIndex + 1 and value == _list[rindex]:
+                rindex += 1
+            rcount = (listIndex + 1) - rindex
+
+            #
+            # adjust the current quantile index based on how many 
+            # numbers in the _list are the same as the current value
+            #
+            newIndex = listIndex
+            if lcount == rcount:
+                if lcount != 0:
+                    #
+                    # there are an equal number of numbers to the left
+                    # and right, try going to the left first unless
+                    # doing so creates an empty quantile.
+                    #
+                    if lindex != lowerBound:
+                        newIndex = lindex
+                    else:
+                        newIndex = rindex - 1
+
+            elif lcount < rcount:
+                # there are fewer items to the left, so 
+                # try going to the left first unless
+                # doing so creates an empty quantile.
+                if lindex != lowerBound:
+                    newIndex = lindex
+                else:
+                    newIndex = rindex - 1
+
+            elif rcount < lcount:
+                # there are fewer items to the right, so go to the right
+                newIndex = rindex - 1
+
+            adjusted = adjusted or newIndex != listIndex
+
+            quantiles[qindex] = newIndex
+            lowerBound = quantiles[qindex]
+
+    if len(quantiles) == 0:
+        return None
+    else:
+        return (adjusted, minIndex, maxIndex,
+                [(q, (q - minIndex+1) / float(numValues)) \
+                 for q in quantiles])
+
+class CustomRamp:
+
+    def __init__(self, prop1, prop2):
+        """Create a ramp between prop1 and prop2."""
+        self.prop1 = prop1
+        self.prop2 = prop2
+
+    def GetRamp(self):
+        """Return this ramp."""
+        return self
+
+    def GetProperties(self, index):
+        """Return a ClassGroupProperties object whose properties
+        represent a point at 'index' between prop1 and prop2 in
+        the constructor.
+
+        index -- a value such that 0 <= index <= 1
+        """
+
+        if not (0 <= index <= 1):
+            raise ValueError(_("invalid index"))
+
+        newProps = ClassGroupProperties()
+
+        self.__SetProperty(self.prop1.GetLineColor(),
+                           self.prop2.GetLineColor(),
+                           index, newProps.SetLineColor)
+        self.__SetProperty(self.prop1.GetFill(), self.prop2.GetFill(),
+                           index, newProps.SetFill)
+
+        w = (self.prop2.GetLineWidth() - self.prop1.GetLineWidth()) \
+            * index \
+            + self.prop1.GetLineWidth()
+        newProps.SetLineWidth(int(round(w)))
+
+        s = (self.prop2.GetSize() - self.prop1.GetSize()) \
+            * index \
+            + self.prop1.GetSize()
+        newProps.SetSize(int(round(s)))
+
+        return newProps
+
+    def __SetProperty(self, color1, color2, index, setf):
+        """Use setf to set the appropriate property for the point
+        index percent between color1 and color2. setf is a function
+        to call that accepts a Color object or Transparent.
+        """
+
+        if color1 is Transparent and color2 is Transparent:
+            setf(Transparent)
+        elif color1 is Transparent:
+            setf(Color(
+                 color2.red   * index,
+                 color2.green * index,
+                 color2.blue  * index))
+        elif color2 is Transparent:
+            setf(Color(
+                 color1.red   * index,
+                 color1.green * index,
+                 color1.blue  * index))
+        else:
+            setf(Color(
+                (color2.red   - color1.red)   * index + color1.red,
+                (color2.green - color1.green) * index + color1.green,
+                (color2.blue  - color1.blue)  * index + color1.blue))
+
+class MonochromaticRamp(CustomRamp):
+    """Helper class to make ramps between two colors."""
+
+    def __init__(self, start, end):
+        """Create a Monochromatic Ramp.
+
+        start -- starting Color
+
+        end -- ending Color
+        """
+        sp = ClassGroupProperties()
+        sp.SetLineColor(start)
+        sp.SetFill(start)
+
+        ep = ClassGroupProperties()
+        ep.SetLineColor(end)
+        ep.SetFill(end)
+
+        CustomRamp.__init__(self, sp, ep)
+
+grey_ramp         = MonochromaticRamp(Color(1, 1, 1),  Color(0, 0, 0))
+red_ramp          = MonochromaticRamp(Color(1, 1, 1),  Color(.8, 0, 0))
+green_ramp        = MonochromaticRamp(Color(1, 1, 1),  Color(0, .8, 0))
+blue_ramp         = MonochromaticRamp(Color(1, 1, 1),  Color(0, 0, .8))
+green_to_red_ramp = MonochromaticRamp(Color(0, .8, 0), Color(1, 0, 0))
+
+class HotToColdRamp:
+    """A ramp that generates properties with colors ranging from
+    'hot' colors (e.g. red, orange) to 'cold' colors (e.g. green, blue)
+    """
+
+    def GetRamp(self):
+        """Return this ramp."""
+        return self
+
+    def GetProperties(self, index):
+        """Return a ClassGroupProperties object whose properties
+        represent a point at 'index' between "hot" and "cold".
+
+        index -- a value such that 0 <= index <= 1
+        """
+
+        clr = [1.0, 1.0, 1.0]
+
+        if index < .25:
+            clr[0] = 0
+            clr[1] = 4 * index
+        elif index < .5:
+            clr[0] = 0
+            clr[2] = 1 + 4 * (.25 - index)
+        elif index < .75:
+            clr[0] = 4 * (index - .5)
+            clr[2] = 0
+        else:
+            clr[1] = 1 + 4 * (.75 - index)
+            clr[2] = 0
+
+        prop = ClassGroupProperties()
+        prop.SetLineColor(Color(clr[0], clr[1], clr[2]))
+        prop.SetFill(Color(clr[0], clr[1], clr[2]))
+
+        return prop
+
+class FixedRamp:
+    """FixedRamp allows particular properties of a ramp to be
+    held constant over the ramp.
+    """
+
+    def __init__(self, ramp, fixes):
+        """
+        ramp -- a source ramp to get the default properties
+
+        fixes -- a tuple (lineColor, lineWidth, fillColor) such that
+             if any item is not None, the appropriate property will 
+             be fixed to that item value.
+        """
+
+        self.fixes = fixes
+        self.ramp = ramp
+
+    def GetRamp(self):
+        """Return this ramp."""
+        return self
+
+    def GetProperties(self, index):
+        """Return a ClassGroupProperties object whose properties
+        represent a point at 'index' between the properties in 
+        the ramp that initialized this FixedRamp.
+
+        index -- a value such that 0 <= index <= 1
+        """
+
+        props = self.ramp.GetProperties(index)
+        if self.fixes[0] is not None: props.SetLineColor(self.fixes[0])
+        if self.fixes[1] is not None: props.SetLineWidth(self.fixes[1])
+        if self.fixes[2] is not None: props.SetFill(self.fixes[2])
+
+        return props

Added: packages/thuban/branches/upstream/current/Thuban/Model/classification.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/classification.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/classification.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,856 @@
+# Copyright (c) 2001, 2003, 2005, 2006 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+# Jan-Oliver Wagner <jan at intevation.de> (2005)
+# Frank Koormann <frank at intevation.de> (2006)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2688 $"
+
+"""
+A Classification provides a mapping from an input value
+to data. This mapping can be specified in two ways. 
+First, specific values can be associated with data. 
+Second, ranges can be associated with data such that if 
+an input value falls with a range that data is returned. 
+If no mapping can be found then default data will 
+be returned. Input values must be hashable objects
+
+See the description of FindGroup() for more information 
+on the mapping algorithm.
+"""
+  
+import copy, operator, types
+import re
+
+from Thuban import _
+
+from messages import \
+    LAYER_PROJECTION_CHANGED, \
+    LAYER_LEGEND_CHANGED, \
+    LAYER_VISIBILITY_CHANGED,\
+    CLASS_CHANGED
+
+from Thuban.Model.color import Color, Transparent, Black
+from Thuban.Model.range import Range
+
+import Thuban.Model.layer
+
+from Thuban.Lib.connector import Publisher
+
+class Classification(Publisher):
+    """Encapsulates the classification of layer. 
+    
+    The Classification divides some kind of data into Groups which 
+    are associated with properties. Later the properties can be 
+    retrieved by matching data values to the appropriate group.
+    """
+
+    def __init__(self):
+        """Initialize a classification."""
+ 
+        self.__groups = []
+
+        self.SetDefaultGroup(ClassGroupDefault())
+
+    def __iter__(self):
+        return ClassIterator(self.__groups) 
+
+    def __deepcopy__(self, memo):
+        clazz = Classification()
+
+        clazz.__groups[0] = copy.deepcopy(self.__groups[0])
+
+        for i in range(1, len(self.__groups)):
+            clazz.__groups.append(copy.deepcopy(self.__groups[i]))
+
+        return clazz
+
+    def __SendNotification(self):
+        """Notify the layer that this class has changed."""
+        self.issue(CLASS_CHANGED)
+
+    def __getattr__(self, attr):
+        """Generate the compiled classification on demand"""
+        if attr == "_compiled_classification":
+            self._compile_classification()
+            return self._compiled_classification
+        raise AttributeError(attr)
+
+    def _compile_classification(self):
+        """Generate the compiled classification
+
+        The compiled classification is a more compact representation of
+        the classification groups that is also more efficient for
+        performing the classification.
+
+        The compiled classification is a list of tuples. The first
+        element of the tuple is a string which describes the rest of the
+        tuple. There are two kinds of tuples:
+
+          'singletons'
+
+            The second element of the tuple is a dictionary which
+            combines several consecutive ClassGroupSingleton instances.
+            The dictionary maps the values of the singletons (as
+            returned by the GetValue() method) to the corresponding
+            group.
+
+          'range'
+
+            The tuple describes a ClassGroupRange instance. The tuples
+            second element is a tuple fo the form (lfunc, min, max,
+            rfunc, group) where group is the original group object,
+            lfunc and rfuct are comparison functions and min and max are
+            lower and upper bounds of the range. Given a value and such
+            a tuple the group matches if and only if
+
+                lfunc(min, value) and rfunc(max, value)
+
+            is true.
+
+          'pattern'
+            
+            The tuple contains the compiled regular expression object and 
+            the original group object.
+
+        The compiled classification is bound to
+        self._compile_classification.
+        """
+        compiled = []
+        for group in self.__groups[1:]:
+            if isinstance(group, ClassGroupSingleton):
+                if not compiled or compiled[-1][0] != "singletons":
+                    compiled.append(("singletons", {}))
+                compiled[-1][1].setdefault(group.GetValue(), group)
+            elif isinstance(group, ClassGroupPattern):
+                pattern = re.compile(group.GetPattern())
+                compiled.append(("pattern", (pattern, group)))
+            elif isinstance(group, ClassGroupRange):
+                left, min, max, right = group.GetRangeTuple()
+                if left == "[":
+                    lfunc = operator.le
+                elif left == "]":
+                    lfunc = operator.lt
+                if right == "[":
+                    rfunc = operator.gt
+                elif right == "]":
+                    rfunc = operator.ge
+                compiled.append(("range", (lfunc, min, max, rfunc, group)))
+            else:
+                raise TypeError("Unknown group type %s", group)
+        self._compiled_classification = compiled
+
+    def _clear_compiled_classification(self):
+        """Reset the compiled classification.
+
+        If will be created on demand when self._compiled_classification
+        is accessed again.
+
+        Call this method whenever self.__groups is modified.
+        """
+        try:
+            del self._compiled_classification
+        except:
+            pass
+
+    #
+    # these SetDefault* methods are really only provided for 
+    # some backward compatibility. they should be considered
+    # for removal once all the classification code is finished.
+    #
+
+    def SetDefaultFill(self, fill):
+        """Set the default fill color.
+
+        fill -- a Color object.
+        """
+        self.GetDefaultGroup().GetProperties().SetFill(fill)
+        self.__SendNotification()
+        
+    def GetDefaultFill(self):
+        """Return the default fill color."""
+        return self.GetDefaultGroup().GetProperties().GetFill()
+        
+    def SetDefaultLineColor(self, color):
+        """Set the default line color.
+
+        color -- a Color object.
+        """
+        self.GetDefaultGroup().GetProperties().SetLineColor(color)
+        self.__SendNotification()
+        
+    def GetDefaultLineColor(self):
+        """Return the default line color."""
+        return self.GetDefaultGroup().GetProperties().GetLineColor()
+        
+    def SetDefaultLineWidth(self, lineWidth):
+        """Set the default line width.
+
+        lineWidth -- an integer > 0.
+        """
+        assert isinstance(lineWidth, types.IntType)
+        self.GetDefaultGroup().GetProperties().SetLineWidth(lineWidth)
+        self.__SendNotification()
+        
+    def GetDefaultLineWidth(self):
+        """Return the default line width."""
+        return self.GetDefaultGroup().GetProperties().GetLineWidth()
+        
+
+    #
+    # The methods that manipulate self.__groups have to be kept in
+    # sync. We store the default group in index 0 to make it
+    # convienent to iterate over the classification's groups, but
+    # from the user's perspective the first (non-default) group is
+    # at index 0 and the DefaultGroup is a special entity.
+    #
+
+    def SetDefaultGroup(self, group):
+        """Set the group to be used when a value can't be classified.
+
+        group -- group that the value maps to.
+        """
+        assert isinstance(group, ClassGroupDefault)
+        if len(self.__groups) > 0:
+            self.__groups[0] = group
+        else:
+            self.__groups.append(group)
+        self.__SendNotification()
+
+    def GetDefaultGroup(self):
+        """Return the default group."""
+        return self.__groups[0]
+
+    def AppendGroup(self, item):
+        """Append a new ClassGroup item to the classification.
+
+        item -- this must be a valid ClassGroup object
+        """
+
+        self.InsertGroup(self.GetNumGroups(), item)
+
+    def InsertGroup(self, index, group):
+        assert isinstance(group, ClassGroup)
+        self.__groups.insert(index + 1, group)
+        self._clear_compiled_classification()
+        self.__SendNotification()
+
+    def RemoveGroup(self, index):
+        """Remove the classification group with the given index"""
+        self.__groups.pop(index + 1)
+        self._clear_compiled_classification()
+        self.__SendNotification()
+
+    def ReplaceGroup(self, index, group):
+        assert isinstance(group, ClassGroup)
+        self.__groups[index + 1] = group
+        self._clear_compiled_classification()
+        self.__SendNotification()
+
+    def GetGroup(self, index):
+        return self.__groups[index + 1]
+
+    def GetNumGroups(self):
+        """Return the number of non-default groups in the classification."""
+        return len(self.__groups) - 1
+
+    def FindGroup(self, value):
+        """Return the group that matches the value.
+
+        Groups are effectively checked in the order the were added to
+        the Classification.
+
+        value -- the value to classify. If there is no mapping or value
+                 is None, return the default properties
+        """
+
+        if value is not None:
+            for typ, params in self._compiled_classification:
+                if typ == "singletons":
+                    group = params.get(value)
+                    if group is not None:
+                        return group
+                elif typ == "range":
+                    lfunc, min, max, rfunc, g = params
+                    if lfunc(min, value) and rfunc(max, value):
+                        return g
+                elif typ == "pattern":
+                    # TODO: make pattern more robust. The following chrashes 
+                    # if accidently be applied on non-string columns. 
+                    # Usually the UI prevents this.
+                    p, g = params
+                    if p.match(value):
+                        return g
+
+        return self.GetDefaultGroup()
+
+    def GetProperties(self, value):
+        """Return the properties associated with the given value.
+       
+        Use this function rather than Classification.FindGroup().GetProperties()
+        since the returned group may be a ClassGroupMap which doesn't support
+        a call to GetProperties(). 
+        """
+
+        group = self.FindGroup(value)
+        if isinstance(group, ClassGroupMap):
+            return group.GetPropertiesFromValue(value)
+        else:
+            return group.GetProperties()
+
+    def TreeInfo(self):
+        items = []
+
+        def build_color_item(text, color):
+            if color is Transparent:
+                return ("%s: %s" % (text, _("None")), None)
+
+            return ("%s: (%.3f, %.3f, %.3f)" % 
+                    (text, color.red, color.green, color.blue),
+                    color)
+
+        def build_item(group, string):
+            label = group.GetLabel()
+            if label == "":
+                label = string
+            else:
+                label += " (%s)" % string
+
+            props = group.GetProperties()
+            i = []
+            v = props.GetLineColor()
+            i.append(build_color_item(_("Line Color"), v))
+            v = props.GetLineWidth()
+            i.append(_("Line Width: %s") % v)
+
+	    # Note: Size is owned by all properties, so
+	    # a size will also appear where it does not
+	    # make sense like for lines and polygons.
+            v = props.GetSize()
+            i.append(_("Size: %s") % v)
+
+            v = props.GetFill()
+            i.append(build_color_item(_("Fill"), v))
+            return (label, i)
+
+        for p in self:
+            items.append(build_item(p, p.GetDisplayText()))
+
+        return (_("Classification"), items)
+
+class ClassIterator:
+    """Allows the Groups in a Classifcation to be interated over.
+
+    The items are returned in the following order:
+        default data, singletons, ranges, maps
+    """
+
+    def __init__(self, data): #default, points, ranges, maps):
+        """Constructor.
+
+        default -- the default group
+
+        points -- a list of singleton groups
+
+        ranges -- a list of range groups
+
+        maps -- a list of map groups
+        """
+
+        self.data = data 
+        self.data_index = 0
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        """Return the next item."""
+
+        if self.data_index >= len(self.data):
+            raise StopIteration
+        else:
+            d = self.data[self.data_index]
+            self.data_index += 1
+            return d
+
+class ClassGroupProperties:
+    """Represents the properties of a single Classification Group.
+
+    These are used when rendering a layer."""
+
+    # TODO: Actually, size is only relevant for point objects.
+    # Eventually it should be spearated, e.g. when introducing symbols.
+
+    def __init__(self, props = None):
+        """Constructor.
+
+        props -- a ClassGroupProperties object. The class is copied if
+                 prop is not None. Otherwise, a default set of properties
+                 is created such that: line color = Black, line width = 1,
+                 size = 5 and fill color = Transparent
+        """
+
+        if props is not None:
+            self.SetProperties(props)
+        else:
+            self.SetLineColor(Black)
+            self.SetLineWidth(1)
+            self.SetSize(5)
+            self.SetFill(Transparent)
+
+    def SetProperties(self, props):
+        """Set this class's properties to those in class props."""
+
+        assert isinstance(props, ClassGroupProperties)
+        self.SetLineColor(props.GetLineColor())
+        self.SetLineWidth(props.GetLineWidth())
+        self.SetSize(props.GetSize())
+        self.SetFill(props.GetFill())
+
+    def GetLineColor(self):
+        """Return the line color as a Color object."""
+        return self.__stroke
+
+    def SetLineColor(self, color):
+        """Set the line color.
+
+        color -- the color of the line. This must be a Color object.
+        """
+
+        self.__stroke = color
+
+    def GetLineWidth(self):
+        """Return the line width."""
+        return self.__strokeWidth
+
+    def SetLineWidth(self, lineWidth):
+        """Set the line width.
+
+        lineWidth -- the new line width. This must be > 0.
+        """
+        assert isinstance(lineWidth, types.IntType)
+        if (lineWidth < 1):
+            raise ValueError(_("lineWidth < 1"))
+
+        self.__strokeWidth = lineWidth
+
+    def GetSize(self):
+        """Return the size."""
+        return self.__size
+
+    def SetSize(self, size):
+        """Set the size.
+
+        size -- the new size. This must be > 0.
+        """
+        assert isinstance(size, types.IntType)
+        if (size < 1):
+            raise ValueError(_("size < 1"))
+
+        self.__size = size
+
+    def GetFill(self):
+        """Return the fill color as a Color object."""
+        return self.__fill
+
+    def SetFill(self, fill):
+        """Set the fill color.
+
+        fill -- the color of the fill. This must be a Color object.
+        """
+
+        self.__fill = fill
+
+    def __eq__(self, other):
+        """Return true if 'props' has the same attributes as this class"""
+
+        #
+        # using 'is' over '==' results in a huge performance gain
+        # in the renderer
+        #
+        return isinstance(other, ClassGroupProperties)   \
+            and (self.__stroke is other.__stroke or      \
+                 self.__stroke == other.__stroke)        \
+            and (self.__fill is other.__fill or          \
+                 self.__fill == other.__fill)            \
+            and self.__strokeWidth == other.__strokeWidth\
+            and self.__size == other.__size
+
+    def __ne__(self, other): 
+        return not self.__eq__(other)
+
+    def __copy__(self):
+        return ClassGroupProperties(self)
+
+    def __deepcopy__(self):
+        return ClassGroupProperties(self)
+
+    def __repr__(self):
+        return repr((self.__stroke, self.__strokeWidth, self.__size,
+                    self.__fill))
+
+class ClassGroup:
+    """A base class for all Groups within a Classification"""
+
+    def __init__(self, label = "", props = None, group = None):
+        """Constructor.
+
+        label -- A string representing the Group's label
+        """
+
+        if group is not None:
+            self.SetLabel(copy.copy(group.GetLabel()))
+            self.SetProperties(copy.copy(group.GetProperties()))
+            self.SetVisible(group.IsVisible())
+        else:
+            self.SetLabel(label)
+            self.SetProperties(props)
+            self.SetVisible(True)
+
+    def GetLabel(self):
+        """Return the Group's label."""
+        return self.label
+
+    def SetLabel(self, label):
+        """Set the Group's label.
+
+        label -- a string representing the Group's label. This must
+                 not be None.
+        """
+        assert isinstance(label, types.StringTypes)
+        self.label = label
+
+    def GetDisplayText(self):
+        assert False, "GetDisplay must be overridden by subclass!"
+        return ""
+
+    def Matches(self, value):
+        """Determines if this Group is associated with the given value.
+
+        Returns False. This needs to be overridden by all subclasses.
+        """
+        assert False, "GetMatches must be overridden by subclass!"
+        return False
+
+    def GetProperties(self):
+        """Return the properties associated with the given value."""
+
+        return self.prop
+ 
+    def SetProperties(self, prop):
+        """Set the properties associated with this Group.
+
+        prop -- a ClassGroupProperties object. if prop is None, 
+                a default set of properties is created.
+        """
+
+        if prop is None: prop = ClassGroupProperties()
+        assert isinstance(prop, ClassGroupProperties)
+        self.prop = prop
+
+    def IsVisible(self):
+        return self.visible
+
+    def SetVisible(self, visible):
+        self.visible = visible
+
+    def __eq__(self, other):
+        return isinstance(other, ClassGroup) \
+            and self.label == other.label \
+            and self.GetProperties() == other.GetProperties()
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __repr__(self):
+        return repr(self.label) + ", " + repr(self.GetProperties())
+    
+class ClassGroupSingleton(ClassGroup):
+    """A Group that is associated with a single value."""
+
+    def __init__(self, value = 0, props = None, label = "", group = None):
+        """Constructor.
+
+        value -- the associated value.
+
+        prop -- a ClassGroupProperites object. If prop is None a default
+                 set of properties is created.
+
+        label -- a label for this group.
+        """
+        ClassGroup.__init__(self, label, props, group)
+
+        self.SetValue(value)
+
+    def __copy__(self):
+        return ClassGroupSingleton(self.GetValue(), 
+                                   self.GetProperties(), 
+                                   self.GetLabel())
+
+    def __deepcopy__(self, memo):
+        return ClassGroupSingleton(self.GetValue(), group = self)
+
+    def GetValue(self):
+        """Return the associated value."""
+        return self.__value
+
+    def SetValue(self, value):
+        """Associate this Group with the given value."""
+        self.__value = value
+
+    def Matches(self, value):
+        """Determine if the given value matches the associated Group value."""
+
+        """Returns True if the value matches, False otherwise."""
+
+        return self.__value == value
+
+    def GetDisplayText(self):
+        label = self.GetLabel()
+
+        if label != "": return label
+
+        return str(self.GetValue())
+
+    def __eq__(self, other):
+        return ClassGroup.__eq__(self, other) \
+            and isinstance(other, ClassGroupSingleton) \
+            and self.__value == other.__value
+
+    def __repr__(self): 
+        return "(" + repr(self.__value) + ", " + ClassGroup.__repr__(self) + ")"
+
+class ClassGroupDefault(ClassGroup):
+    """The default Group. When values do not match any other
+       Group within a Classification, the properties from this
+       class are used."""
+
+    def __init__(self, props = None, label = "", group = None):
+        """Constructor.
+
+        prop -- a ClassGroupProperites object. If prop is None a default
+                 set of properties is created.
+
+        label -- a label for this group.
+        """
+
+        ClassGroup.__init__(self, label, props, group)
+
+    def __copy__(self):
+        return ClassGroupDefault(self.GetProperties(), self.GetLabel())
+
+    def __deepcopy__(self, memo):
+        return ClassGroupDefault(label = self.GetLabel(), group = self)
+
+    def Matches(self, value):
+        return True
+
+    def GetDisplayText(self):
+        label = self.GetLabel()
+
+        if label != "": return label
+
+        return _("DEFAULT")
+
+    def __eq__(self, other):
+        return ClassGroup.__eq__(self, other) \
+            and isinstance(other, ClassGroupDefault) \
+            and self.GetProperties() == other.GetProperties()
+
+    def __repr__(self): 
+        return "(" + ClassGroup.__repr__(self) + ")"
+
+class ClassGroupRange(ClassGroup):
+    """A Group that represents a range of values that map to the same
+       set of properties."""
+
+    def __init__(self, _range = (0,1), props = None, label = "", group=None):
+        """Constructor.
+
+        The minumum value must be strictly less than the maximum.
+
+        _range -- either a tuple (min, max) where min < max or
+                  a Range object
+
+        prop -- a ClassGroupProperites object. If prop is None a default
+                 set of properties is created.
+
+        label -- a label for this group.
+        """
+
+        ClassGroup.__init__(self, label, props, group)
+        self.SetRange(_range)
+
+    def __copy__(self):
+        return ClassGroupRange(self.__range,
+                               props = self.GetProperties(), 
+                               label = self.GetLabel())
+
+    def __deepcopy__(self, memo):
+        return ClassGroupRange(copy.copy(self.__range), 
+                               group = self)
+
+    def GetMin(self):
+        """Return the range's minimum value."""
+        return self.__range.GetRange()[1]
+
+    def SetMin(self, min):
+        """Set the range's minimum value.
+     
+        min -- the new minimum. Note that this must be less than the current
+               maximum value. Use SetRange() to change both min and max values.
+        """
+     
+        self.SetRange((min, self.__range.GetRange()[2]))
+
+    def GetMax(self):
+        """Return the range's maximum value."""
+        return self.__range.GetRange()[2]
+
+    def SetMax(self, max):
+        """Set the range's maximum value.
+     
+        max -- the new maximum. Note that this must be greater than the current
+               minimum value. Use SetRange() to change both min and max values.
+        """
+        self.SetRange((self.__range.GetRange()[1], max))
+
+    def SetRange(self, _range):
+        """Set a new range.
+
+        _range -- Either a tuple (min, max) where min < max or
+                  a Range object.
+
+        Raises ValueError on error.
+        """
+
+        if isinstance(_range, Range):
+            self.__range = _range
+        elif isinstance(_range, types.TupleType) and len(_range) == 2:
+            self.__range = Range(("[", _range[0], _range[1], "["))
+        else:
+            raise ValueError()
+
+    def GetRange(self):
+        """Return the range as a string"""
+        return self.__range.string(self.__range.GetRange())
+
+    def GetRangeTuple(self):
+        return self.__range.GetRange()
+
+    def Matches(self, value):
+        """Determine if the given value lies with the current range.
+
+        The following check is used: min <= value < max.
+        """
+
+        return operator.contains(self.__range, value)
+
+    def GetDisplayText(self):
+        label = self.GetLabel()
+
+        if label != "": return label
+
+        return self.__range.string(self.__range.GetRange())
+
+    def __eq__(self, other):
+        return ClassGroup.__eq__(self, other) \
+            and isinstance(other, ClassGroupRange) \
+            and self.__range == other.__range
+
+    def __repr__(self): 
+        return "(" + str(self.__range) + ClassGroup.__repr__(self) + ")"
+
+class ClassGroupPattern(ClassGroup):
+    """A Group that is associated with a reg exp pattern."""
+
+    def __init__(self, pattern = "", props = None, label = "", group = None):
+        """Constructor.
+
+        pattern -- the associated pattern.
+
+        props   -- a ClassGroupProperites object. If props is None a default
+                   set of properties is created.
+
+        label   -- a label for this group.
+        """
+        ClassGroup.__init__(self, label, props, group)
+
+        self.SetPattern(pattern)
+
+    def __copy__(self):
+        return ClassGroupPattern(self.GetPattern(), 
+                                   self.GetProperties(), 
+                                   self.GetLabel())
+
+    def __deepcopy__(self, memo):
+        return ClassGroupPattern(self.GetPattern(), group = self)
+
+    def GetPattern(self):
+        """Return the associated pattern."""
+        return self.__pattern
+
+    def SetPattern(self, pattern):
+        """Associate this Group with the given pattern."""
+        self.__pattern = pattern
+
+    def Matches(self, pattern):
+        """Check if the given pattern matches the associated Group pattern."""
+
+        """Returns True if the value matches, False otherwise."""
+
+        if re.match(self.__pattern, pattern):
+            return True
+        else:
+            return False
+
+    def GetDisplayText(self):
+        label = self.GetLabel()
+
+        if label != "": return label
+
+        return str(self.GetPattern())
+
+    def __eq__(self, other):
+        return ClassGroup.__eq__(self, other) \
+            and isinstance(other, ClassGroupPattern) \
+            and self.__pattern == other.__pattern
+
+    def __repr__(self): 
+        return "(" + repr(self.__pattern) + ", " + ClassGroup.__repr__(self) + ")"
+
+class ClassGroupMap(ClassGroup):
+    """Currently, this class is not used."""
+
+    FUNC_ID = "id"
+
+    def __init__(self, map_type = FUNC_ID, func = None, prop = None, label=""):
+        ClassGroup.__init__(self, label)
+
+        self.map_type = map_type
+        self.func = func
+
+        if self.func is None:
+            self.func = func_id
+
+    def Map(self, value):
+        return self.func(value)
+
+    def GetProperties(self):
+        return None
+
+    def GetPropertiesFromValue(self, value):
+        pass
+
+    def GetDisplayText(self):
+        return "Map: " + self.map_type
+
+    #
+    # built-in mappings
+    #
+    def func_id(value):
+        return value
+

Added: packages/thuban/branches/upstream/current/Thuban/Model/color.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/color.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/color.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,60 @@
+# Copyright (c) 2001, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 1546 $"
+
+class Color:
+    """An RGB color. RGB values are floats in the range 0.0 .. 1.0
+
+    Color objects should be treated as immutable
+    """
+
+    def __init__(self, red, green, blue):
+        self.red = red
+        self.green = green
+        self.blue = blue
+
+    def hex(self):
+        """Return the color as a HTML/CSS hex code"""
+        return "#%02x%02x%02x" % (255 * self.red,
+                                  255 * self.green,
+                                  255 * self.blue)
+
+    def __eq__(self, other):
+        """Test equality with other Color objects."""
+        return isinstance(other, Color)   \
+            and self.red   == other.red   \
+            and self.green == other.green \
+            and self.blue  == other.blue
+
+    def __ne__(self, other):
+        """Test inequality with other Color objects."""
+        return not self.__eq__(other)
+
+    def __repr__(self):
+        """Return a string of the rgb values"""
+        return "Color(%r, %r, %r)" % (self.red, self.green, self.blue)
+
+class _Transparent: 
+    """An object which represents no color."""
+
+    def hex(self):
+        return "None"
+
+    def __eq__(self, other):
+        return isinstance(other, _Transparent)
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __repr__(self):
+        return "Transparent"
+
+Transparent = _Transparent()
+Black = Color(0, 0, 0)
+

Added: packages/thuban/branches/upstream/current/Thuban/Model/data.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/data.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/data.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,385 @@
+# Copyright (C) 2003, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Data source abstractions"""
+
+from __future__ import generators
+
+__version__ = "$Revision: 2605 $"
+# $Source$
+# $Id: data.py 2605 2005-04-27 11:04:56Z jan $
+
+import os
+import weakref
+from math import ceil, log
+
+import shapelib
+import shptree
+import table
+import transientdb
+
+from Thuban import _
+
+# Shape type constants
+SHAPETYPE_POLYGON = "polygon"
+SHAPETYPE_ARC = "arc"
+SHAPETYPE_POINT = "point"
+
+# mapping from shapelib shapetype constants to our constants
+shapelib_shapetypes = {shapelib.SHPT_POLYGON: SHAPETYPE_POLYGON,
+                       shapelib.SHPT_ARC: SHAPETYPE_ARC,
+                       shapelib.SHPT_POINT: SHAPETYPE_POINT}
+
+#
+# Raw shape data formats
+#
+
+# Raw data is the same as that returned by the points method.
+RAW_PYTHON = "RAW_PYTHON"
+
+# Raw data is a shapefile. The Shape object will use the shapeid as the
+# raw data.
+RAW_SHAPEFILE = "RAW_SHAPEFILE"
+
+# Raw data in well-known text format
+RAW_WKT = "RAW_WKT"
+
+
+class ShapefileShape:
+
+    """Represent one shape of a shapefile"""
+
+    def __init__(self, shapefile, shapeid):
+        self.shapefile = shapefile
+        self.shapeid = shapeid
+
+    def compute_bbox(self):
+        """
+        Return the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
+        """
+        xs = []
+        ys = []
+        for part in self.Points():
+            for x, y in part:
+                xs.append(x)
+                ys.append(y)
+        return (min(xs), min(ys), max(xs), max(ys))
+
+    def ShapeID(self):
+        return self.shapeid
+
+    def Points(self):
+        """Return the coordinates of the shape as a list of lists of pairs"""
+        shape = self.shapefile.read_object(self.shapeid)
+        points = shape.vertices()
+        if self.shapefile.info()[1] == shapelib.SHPT_POINT:
+            points = [points]
+        return points
+
+    def RawData(self):
+        """Return the shape id to use with the shapefile"""
+        return self.shapeid
+
+    def Shapefile(self):
+        """Return the shapefile object"""
+        return self.shapefile
+
+
+class ShapeTable(transientdb.AutoTransientTable):
+
+    """A Table that depends on a ShapefileStore
+
+    Intended use is by the ShapefileStore for the table associated with
+    the shapefiles.
+    """
+
+    def __init__(self, store, db, table):
+        """Initialize the ShapeTable.
+
+        Parameters:
+            store -- the ShapefileStore the table is to depend on
+            db -- The transient database to use
+            table -- the table
+        """
+        transientdb.AutoTransientTable.__init__(self, db, table)
+        self.store = weakref.ref(store)
+
+    def Dependencies(self):
+        """Return a tuple containing the shapestore"""
+        return (self.store(),)
+
+# XXX: (this statement should be kept in mind when re-engeneering)
+#
+# From a desing POV it was wrong to distinguish between table and
+# shapestore.  In hindsight the only reason for doing so was that the
+# shapelib has different objects for the shapefile(s) and the dbf file,
+# which of course matches the way the data is organized into different
+# files.  So the distinction between shapestore and table is an artifact
+# of the shapefile format.  When we added the postgis support we should
+# have adopted the table interface for the entire shape store, making the
+# geometry data an additional column for those shape stores that don't
+# store the geometries in columns in the first place.
+
+class FileShapeStore:
+
+    """The base class to derive any file-based ShapeStore from.
+
+    This class contains all information that is needed by a
+    loader routine to actually load the shapestore.
+    This essentially means that the class contains all required information
+    to save the shapestore specification (i.e. in a .thuban file).
+    """
+
+    def __init__(self, filename, sublayer_name = None):
+        """Initialize the base class with main parameters.
+
+        filename  -- the source filename.
+                     This filename will be converted to an absolute filename.
+                     The filename will be interpreted relative to the .thuban file anyway,
+                     but when saving a session we need to compare absolute paths
+                     and it's usually safer to always work with absolute paths.
+        sublayer_name -- a string representing a layer within the file shape store.
+                     Some file formats support to contain several layers, or
+                     at least the ogr library says so.
+                     For those filetypes who don't, the sublayer_name can be ignored
+                     and by default it is None.
+        """
+        self._filename = os.path.abspath(filename)
+        self._sublayer_name = sublayer_name
+
+    def FileName(self):
+        """Return the filename used to open the shapestore.
+
+        The filename can only be set via __init__ method.
+        """
+        return self._filename
+
+    def FileType(self):
+        """Return the filetype.
+
+        The filetype has to be set in all derived classes.
+        It must be string.
+        Known and used types are: "shapefile"
+        """
+        raise NotImplementedError
+
+    def SublayerName(self):
+        """Return the sublayer_name.
+
+        This could be None if the shapestore type only supports a single
+        layer.
+        """
+        return self._sublayer_name
+
+    # Design/Implementation note:
+    # It is not a good idea to have a implementation for a
+    # "setBoundingBox" or BoundingBox in this base class.
+    # In future this data might change during
+    # a Thuban session and thus can not be kept statically here.
+    # It is expected that for many derived classes the bbox must
+    # be retrieved each time anew.
+
+    def BoundingBox(self):
+        """Return the bounding box of the shapes in the shape store.
+
+        The coordinate system used is whatever was used in the shape store.
+        If the shape store is empty, return None.
+        """
+        raise NotImplementedError
+
+class ShapefileStore(FileShapeStore):
+
+    """Combine a shapefile and the corresponding DBF file into one object"""
+
+    def __init__(self, session, filename):
+        FileShapeStore.__init__(self, filename)
+
+        self.dbftable = table.DBFTable(filename)
+        self._table = ShapeTable(self, session.TransientDB(), self.dbftable)
+        self._bbox = None
+        self._open_shapefile()
+
+    def _open_shapefile(self):
+        self.shapefile = shapelib.ShapeFile(self.FileName())
+        self.numshapes, shapetype, mins, maxs = self.shapefile.info()
+        if self.numshapes:
+            self._bbox = mins[:2] + maxs[:2]
+        else:
+            self._bbox = None
+        self.shapetype = shapelib_shapetypes[shapetype]
+
+        # estimate a good depth for the quad tree. Each depth multiplies
+        # the number of nodes by four, therefore we basically take the
+        # base 4 logarithm of the number of shapes.
+        if self.numshapes < 4:
+            maxdepth = 1
+        else:
+            maxdepth = int(ceil(log(self.numshapes / 4.0) / log(4)))
+
+        self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2,
+                                         maxdepth)
+
+    def Table(self):
+        """Return the table containing the attribute data."""
+        return self._table
+
+    def Shapefile(self):
+        """Return the shapefile object"""
+        return self.shapefile
+
+    def FileType(self):
+        """Return the filetype. This is always the string 'shapefile'"""
+        return "shapefile"
+
+    def ShapeType(self):
+        """Return the type of the shapes in the shapestore.
+
+        This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.
+        """
+        return self.shapetype
+
+    def RawShapeFormat(self):
+        """Return the raw data format of the shape data, i.e. RAW_SHAPEFILE"""
+        return RAW_SHAPEFILE
+
+    def NumShapes(self):
+        """Return the number of shapes in the shapefile"""
+        return self.numshapes
+
+    def Dependencies(self):
+        """Return the empty tuple.
+
+        The ShapefileStore doesn't depend on anything else.
+        """
+        return ()
+
+    def OrigShapeStore(self):
+        """Return None.
+
+        The ShapefileStore was not derived from another shapestore.
+        """
+        return None
+
+    def BoundingBox(self):
+        """Return the bounding box of the shapes in the shapefile.
+
+        The coordinate system used is whatever was used in the shapefile.
+        If the shapefileis empty, return None.
+        """
+        return self._bbox
+
+    def ShapesInRegion(self, bbox):
+        """Return an iterable over the shapes that overlap the bounding box.
+
+        The bbox parameter should be the bounding box as a tuple in the
+        form (minx, miny, maxx, maxy) in the coordinate system of the
+        shapefile.
+        """
+        # Bind a few globals to locals to make it a bit faster
+        cls = ShapefileShape
+        shapefile = self.shapefile
+
+        left, bottom, right, top = bbox
+        for i in self.shapetree.find_shapes((left, bottom), (right, top)):
+            yield cls(shapefile, i)
+
+    def AllShapes(self):
+        """Return an iterable over the shapes in the shapefile."""
+        for i in xrange(self.NumShapes()):
+            yield ShapefileShape(self.shapefile, i)
+
+    def Shape(self, index):
+        """Return the shape with index index"""
+        return ShapefileShape(self.shapefile, index)
+
+
+class DerivedShapeStore:
+
+    """A ShapeStore derived from other shapestores or tables"""
+
+    def __init__(self, shapestore, table):
+        """Initialize the derived shapestore.
+
+        The arguments are a shapestore for the shapedata and a table for
+        the tabular data.
+
+        Raises ValueError if the number of shapes in the shapestore
+        is different from the number of rows in the table.
+        """
+
+        numShapes = shapestore.Shapefile().info()[0]
+        if numShapes != table.NumRows():
+            raise ValueError(_("Table not compatible with shapestore."))
+
+        self.shapestore = shapestore
+        self.table = table
+
+    def Table(self):
+        """Return the table"""
+        return self.table
+
+    def Shapefile(self):
+        """Return the shapefile of the underlying shapestore"""
+        return self.shapestore.Shapefile()
+
+    def Dependencies(self):
+        """Return a tuple containing the shapestore and the table"""
+        return (self.shapestore, self.table)
+
+    def OrigShapeStore(self):
+        """
+        Return the original shapestore the derived store was instantiated with
+        """
+        return self.shapestore
+
+    def Shape(self, index):
+        """Return the shape with index index"""
+        return self.shapestore.Shape(index)
+
+    def ShapesInRegion(self, bbox):
+        """Return the ids of the shapes that overlap the box.
+
+        This method is simply delegated to the shapestore the
+        DerivedShapeStore was instantiated with.
+        """
+        return self.shapestore.ShapesInRegion(bbox)
+
+    def AllShapes(self):
+        """Return an iterable over the shapes in the shapefile.
+
+        This method is simply delegated to the shapestore the
+        DerivedShapeStore was instantiated with.
+        """
+        return self.shapestore.AllShapes()
+
+    def ShapeType(self):
+        """Return the type of the shapes in the layer.
+
+        This method is simply delegated to the shapestore the
+        DerivedShapeStore was instantiated with.
+        """
+        return self.shapestore.ShapeType()
+
+    def RawShapeFormat(self):
+        """Return the raw data format of the shapes.
+
+        This method is simply delegated to the shapestore the
+        DerivedShapeStore was instantiated with.
+        """
+        return self.shapestore.RawShapeFormat()
+
+    def NumShapes(self):
+        """Return the number of shapes in the shapestore."""
+        return self.shapestore.NumShapes()
+
+    def BoundingBox(self):
+        """Return the bounding box of the shapes in the shapestore.
+
+        This method is simply delegated to the shapestore the
+        DerivedShapeStore was instantiated with.
+        """
+        return self.shapestore.BoundingBox()

Added: packages/thuban/branches/upstream/current/Thuban/Model/extension.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/extension.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/extension.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,92 @@
+# Copyright (c) 2001, 2002 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2355 $"
+
+from Thuban import _
+
+from messages import EXTENSION_CHANGED, EXTENSION_OBJECTS_CHANGED
+
+from base import TitledObject, Modifiable
+
+
+class Extension(TitledObject, Modifiable):
+
+    """Represent a extension. A extension is a package of additional
+       functionality to Thuban and contains a number of Objects
+       that can be freely defined in an extension.
+       Each object must a a TitleObject with additional set "object.name".
+       Furthermore, each object must implement the methods Subscribe,
+       Unsubscribe and Destroy (i.e. derive from Modifiable).
+
+    Extension objects send the following message types:
+
+        EXTENSION_CHANGED -- Something in the extension has changed.
+
+        EXTENSION_OBJECTS_CHANGED -- Something in the objects has changed.
+
+    """
+
+    forwarded_channels = (EXTENSION_CHANGED, EXTENSION_OBJECTS_CHANGED)
+
+    def __init__(self, title):
+        """Initialize the extension."""
+        TitledObject.__init__(self, title)
+        self.objects = []
+
+    def Destroy(self):
+        for object in self.objects:
+            object.Destroy()
+        Modifiable.Destroy(self)
+
+    def AddObject(self, object):
+        self.objects.append(object)
+        for channel in self.forwarded_channels:
+            object.Subscribe(channel, self.forward, channel)
+        self.changed(EXTENSION_OBJECTS_CHANGED, self)
+
+    def RemoveObject(self, object):
+        for channel in self.forwarded_channels:
+            object.Unsubscribe(channel, self.forward, channel)
+        self.layers.remove(layer)
+        self.changed(EXTENSION_OBJECTS_CHANGED, self)
+        object.Destroy()
+
+    def Objects(self):
+        return self.objects
+
+    def HasObjects(self):
+        return len(self.objects) > 0
+
+    def FindObject(self, title):
+        """Find an object by title. If found, return it, else return None."""
+        for object in self.objects:
+            if object.title == title:
+                return object
+        return None
+
+    def forward(self, *args):
+        """Reissue events"""
+        if len(args) > 1:
+            args = (args[-1],) + args[:-1]
+        apply(self.issue, args)
+
+    def WasModified(self):
+        """Return true if something of the extension was modified"""
+        if self.modified:
+            return 1
+        else:
+            return 0
+
+    def UnsetModified(self):
+        """Unset the modified flag of the extension"""
+        Modifiable.UnsetModified(self)
+
+    def TreeInfo(self):
+        return (_("Extension: %s") % self.title,
+                ["%s: %s" % (object.title, object.name)
+                 for object in self.objects])

Added: packages/thuban/branches/upstream/current/Thuban/Model/label.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/label.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/label.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,92 @@
+# Copyright (c) 2001, 2002, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2569 $"
+
+from Thuban import _
+
+from messages import CHANGED
+
+from base import TitledObject, Modifiable
+
+ALIGN_CENTER = "center"
+ALIGN_TOP = "top"
+ALIGN_BOTTOM = "bottom"
+ALIGN_LEFT = "left"
+ALIGN_RIGHT = "right"
+ALIGN_BASELINE = "baseline"
+
+class Label:
+
+    """This class repesents a single label.
+
+    The label is defined by its coordinate, the text as well
+    as vertical and horizontal alignment concerning
+    the coordinate.
+    """
+
+    def __init__(self, x, y, text, halign, valign):
+        """Initialize the label with the given parameters."""
+        self.x = x
+        self.y = y
+        self.text = text
+        self.halign = halign
+        self.valign = valign
+
+
+class LabelLayer(TitledObject, Modifiable):
+
+    """This represent a layer holding a number of labels."""
+
+    def __init__(self, title):
+        """Initialize the LabeleLayer.
+
+        Initialization is done with an empty
+        list of labels and set the title to "title".
+        """
+        TitledObject.__init__(self, title)
+        Modifiable.__init__(self)
+        self.labels = []
+
+    def Labels(self):
+        """Return a list of all labels."""
+        return self.labels
+
+    def AddLabel(self, x, y, text, halign = ALIGN_LEFT,
+                 valign = ALIGN_CENTER):
+        """Add a label at position (x,y) with contents "text".
+
+        This will emit a CHANGED signal.
+        """
+        self.labels.append(Label(x, y, text, halign, valign))
+        self.changed(CHANGED)
+
+    def RemoveLabel(self, index):
+        """Remove the label specified by index.
+
+        This will emit a CHANGED signal.
+        """
+        del self.labels[index]
+        self.changed(CHANGED)
+
+    def ClearLabels(self):
+        """Remove all labels.
+
+        This will emit a CHANGED signal.
+        """
+        del self.labels[:]
+        self.changed(CHANGED)
+
+    def TreeInfo(self):
+        """Return a description of the object.
+
+        A tuple of (title, tupel) describing the contents
+        of the object in a tree-structure is returned.
+        """
+        items = []
+        items.append(_("Number of labels: %d") % len(self.labels))
+        return (_("Label Layer: %s") % self.title, items)

Added: packages/thuban/branches/upstream/current/Thuban/Model/layer.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/layer.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/layer.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,584 @@
+# Copyright (c) 2001, 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Jonathan Coles <jonathan at intevation.de>
+# Silke Reimer <silke at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2710 $"
+
+import os
+import warnings
+
+from wxproj import point_in_polygon_shape, shape_centroid
+
+from Thuban import _
+
+from messages import LAYER_PROJECTION_CHANGED, LAYER_VISIBILITY_CHANGED, \
+     LAYER_CHANGED, LAYER_SHAPESTORE_REPLACED, CLASS_CHANGED
+
+import classification
+
+from color import Transparent, Black
+from base import TitledObject, Modifiable
+from data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
+from label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
+     ALIGN_LEFT, ALIGN_RIGHT
+
+import resource
+
+from color import Color
+
+shapetype_names = {SHAPETYPE_POINT: "Point",
+                   SHAPETYPE_ARC: "Arc",
+                   SHAPETYPE_POLYGON: "Polygon"}
+
+class BaseLayer(TitledObject, Modifiable):
+
+    """Base class for the layers."""
+
+    def __init__(self, title, visible = True, projection = None):
+        """Initialize the layer.
+
+        title -- the title
+        visible -- boolean. If true the layer is visible.
+        """
+        TitledObject.__init__(self, title)
+        Modifiable.__init__(self)
+        self.visible = visible
+        self.projection = projection
+
+    def Visible(self):
+        """Return true if layer is visible"""
+        return self.visible
+
+    def SetVisible(self, visible):
+        """Set the layer's visibility."""
+        self.visible = visible
+        self.issue(LAYER_VISIBILITY_CHANGED, self)
+
+    def HasClassification(self):
+        """Determine if this layer supports classifications."""
+        return False
+
+    def HasShapes(self):
+        """Determine if this layer supports shapes."""
+        return False
+
+    def GetProjection(self):
+        """Return the layer's projection."""
+        return self.projection
+
+    def SetProjection(self, projection):
+        """Set the layer's projection."""
+        self.projection = projection
+        self.changed(LAYER_PROJECTION_CHANGED, self)
+
+    def Type(self):
+        return "Unknown"
+
+class Layer(BaseLayer):
+
+    """Represent the information of one geodata file (currently a shapefile)
+
+    All children of the layer have the same type.
+
+    A layer has fill and stroke colors. Colors should be instances of
+    Color. They can also be Transparent, indicating no fill or no stroke.
+
+    The layer objects send the following events, all of which have the
+    layer object as parameter:
+
+        TITLE_CHANGED -- The title has changed.
+        LAYER_PROJECTION_CHANGED -- the projection has changed.
+    """
+
+    def __init__(self, title, data, projection = None,
+                 fill = Transparent, 
+                 stroke = Black, 
+                 lineWidth = 1, 
+                 visible = True):
+        """Initialize the layer.
+
+        title -- the title
+        data -- datastore object for the shape data shown by the layer
+        projection -- the projection object. Its Inverse method is
+               assumed to map the layer's coordinates to lat/long
+               coordinates
+        fill -- the fill color or Transparent if the shapes are 
+                not filled
+        stroke -- the stroke color or Transparent if the shapes 
+                are not stroked
+        visible -- boolean. If true the layer is visible.
+
+        colors are expected to be instances of Color class
+        """
+        BaseLayer.__init__(self, title, 
+                                 visible = visible,
+                                 projection = projection)
+
+        self.__classification = None
+        self.store = None
+
+        self.SetShapeStore(data)
+
+        self.classification_column = None
+        self.SetClassificationColumn(None)
+        self.SetClassification(None)
+
+        self.__classification.SetDefaultLineColor(stroke)
+        self.__classification.SetDefaultLineWidth(lineWidth)
+        self.__classification.SetDefaultFill(fill)
+
+        self.UnsetModified()
+
+    def SetShapeStore(self, store):
+        # Set the classification to None if there is a classification
+        # and the new shapestore doesn't have a table with a suitable
+        # column, i.e one with the same name and type as before
+        # FIXME: Maybe we should keep it the same if the type is
+        # compatible enough such as FIELDTYPE_DOUBLE and FIELDTYPE_INT
+        if self.__classification is not None:
+            columnname = self.classification_column
+            columntype = self.GetFieldType(columnname)
+            table = store.Table()
+            if (columnname is not None
+                and (not table.HasColumn(columnname)
+                     or table.Column(columnname).type != columntype)):
+                self.SetClassification(None)
+
+        self.store = store
+
+        self.changed(LAYER_SHAPESTORE_REPLACED, self)
+
+    def ShapeStore(self):
+        return self.store
+
+    def Destroy(self):
+        BaseLayer.Destroy(self)
+        if self.__classification is not None:
+            self.__classification.Unsubscribe(CLASS_CHANGED,
+                                              self._classification_changed)
+
+    def BoundingBox(self):
+        """Return the layer's bounding box in the intrinsic coordinate system.
+
+        If the layer has no shapes, return None.
+        """
+        return self.store.BoundingBox()
+
+    def LatLongBoundingBox(self):
+        """Return the layer's bounding box in lat/long coordinates.
+
+        Return None, if the layer doesn't contain any shapes.
+        """
+        bbox = self.BoundingBox()
+        if bbox is not None and self.projection is not None:
+            bbox = self.projection.InverseBBox(bbox)
+        return bbox
+
+    def Type(self):
+        return self.ShapeType();
+
+    def ShapesBoundingBox(self, shapes):
+        """Return a bounding box in lat/long coordinates for the given
+        list of shape ids.
+
+        If shapes is None or empty, return None.
+        """
+
+        if shapes is None or len(shapes) == 0: return None
+
+        xs = []
+        ys = []
+
+        for id in shapes:
+            bbox = self.Shape(id).compute_bbox()
+            if self.projection is not None:
+                bbox = self.projection.InverseBBox(bbox)
+            left, bottom, right, top = bbox
+            xs.append(left); xs.append(right)
+            ys.append(bottom); ys.append(top)
+
+        return (min(xs), min(ys), max(xs), max(ys))
+
+
+    def GetFieldType(self, fieldName):
+        if self.store:
+            table = self.store.Table()
+            if table.HasColumn(fieldName):
+                return table.Column(fieldName).type
+        return None
+
+    def HasShapes(self):
+        return True
+
+    def NumShapes(self):
+        """Return the number of shapes in the layer"""
+        return self.store.NumShapes()
+
+    def ShapeType(self):
+        """Return the type of the shapes in the layer.
+
+        The return value is one of the SHAPETYPE_* constants defined in
+        Thuban.Model.data.
+        """
+        return self.store.ShapeType()
+
+    def Shape(self, index):
+        """Return the shape with index index"""
+        return self.store.Shape(index)
+
+    def ShapesInRegion(self, bbox):
+        """Return an iterable over the shapes that overlap the bounding box.
+
+        The bbox parameter should be the bounding box as a tuple in the
+        form (minx, miny, maxx, maxy) in unprojected coordinates.
+        """
+        if self.projection is not None:
+            # Ensure that region lies within the layer's bounding box
+            # Otherwise projection of the region would lead to incorrect
+            # values.
+            clipbbox = self.__mangle_bounding_box(bbox)
+            bbox = self.projection.ForwardBBox(clipbbox)
+        return self.store.ShapesInRegion(bbox)
+
+    def GetClassificationColumn(self):
+        return self.classification_column
+
+    def SetClassificationColumn(self, column):
+        """Set the column to classifiy on, or None. If column is not None
+        and the column does not exist in the table, raise a ValueError.
+        """
+        if column:
+            columnType = self.GetFieldType(column)
+            if columnType is None:
+                raise ValueError()
+        changed = self.classification_column != column
+        self.classification_column = column
+        if changed:
+            self.changed(LAYER_CHANGED, self)
+
+    def HasClassification(self):
+        return True
+
+    def GetClassification(self):
+        return self.__classification
+
+    def SetClassification(self, clazz):
+        """Set the classification used by this layer to 'clazz'
+
+        If 'clazz' is None a default classification is created.
+
+        This issues a LAYER_CHANGED event.
+        """
+
+        if self.__classification is not None:
+            self.__classification.Unsubscribe(CLASS_CHANGED,
+                                              self._classification_changed)
+
+        if clazz is None:
+            clazz = classification.Classification()
+
+        self.__classification = clazz
+        self.__classification.Subscribe(CLASS_CHANGED,
+                                        self._classification_changed)
+
+        self._classification_changed()
+
+    def _classification_changed(self):
+        """Called from the classification object when it has changed."""
+        self.changed(LAYER_CHANGED, self)
+ 
+    def TreeInfo(self):
+        items = []
+
+        items.append(_("Filename: %s") % self.ShapeStore().FileName())
+
+        if self.Visible():
+            items.append(_("Shown"))
+        else:
+            items.append(_("Hidden"))
+        items.append(_("Shapes: %d") % self.NumShapes())
+
+        bbox = self.LatLongBoundingBox()
+        if bbox is not None:
+            items.append(_("Extent (lat-lon): (%g, %g, %g, %g)") % tuple(bbox))
+        else:
+            items.append(_("Extent (lat-lon):"))
+        items.append(_("Shapetype: %s") % shapetype_names[self.ShapeType()])
+
+        if self.projection and len(self.projection.params) > 0:
+            items.append((_("Projection"),
+                        [str(param) for param in self.projection.params]))
+
+        items.append(self.__classification)
+
+        return (_("Layer '%s'") % self.Title(), items)
+
+    def __mangle_bounding_box(self, bbox):
+        # FIXME: This method doesn't make much sense.
+        # See RT #2845 which effectively says:
+        #
+        # If this method, which was originally called ClipBoundingBox,
+        # is supposed to do clipping it shouldn't return the parameter
+        # unchanged when it lies completely outside of the bounding box.
+        # It would be better to return None and return an empty list in
+        # ShapesInRegion (the only caller) in that case.
+        #
+        # This method was introduced to fix a bug that IIRC had
+        # something todo with projections and bounding boxes containing
+        # NaN or INF when the parameter to ShapesInRegion covered the
+        # entire earth or something similarly large).
+        bminx, bminy, bmaxx, bmaxy = bbox
+        lminx, lminy, lmaxx, lmaxy = self.LatLongBoundingBox()
+        if bminx > lmaxx or bmaxx < lminx:
+            left, right = bminx, bmaxx
+        else:
+            left = max(lminx, bminx)
+            right = min(lmaxx, bmaxx)
+        if bminy > lmaxy or bmaxy < lminy:
+            bottom, top = bminy, bmaxy
+        else:
+            bottom = max(lminy, bminy)
+            top = min(lmaxy, bmaxy)
+
+        return (left, bottom, right, top)
+
+    def GetLabelPosFromShape(self, cmap, shape_index):
+        '''
+        Return the label position parameters (x, y, halign, valign) from the
+        shape object
+        '''
+        proj = cmap.projection
+        if proj is not None:
+            map_proj = proj
+        else:
+            map_proj = None
+        proj = self.projection
+        if proj is not None:
+            layer_proj = proj
+        else:
+            layer_proj = None
+
+        shapetype = self.ShapeType()
+        if shapetype == SHAPETYPE_POLYGON:
+            shapefile = self.ShapeStore().Shapefile().cobject()
+            x, y = shape_centroid(shapefile, shape_index,
+                                  map_proj, layer_proj, 1, 1, 0, 0)
+            if map_proj is not None:
+                x, y = map_proj.Inverse(x, y)
+        else:
+            shape = self.Shape(shape_index)
+            if shapetype == SHAPETYPE_POINT:
+                x, y = shape.Points()[0][0]
+            else:
+                # assume SHAPETYPE_ARC
+                points = shape.Points()[0]
+                x, y = points[len(points) / 2]
+            if layer_proj is not None:
+                x, y = layer_proj.Inverse(x, y)
+        if shapetype == SHAPETYPE_POINT:
+            halign = ALIGN_LEFT
+            valign = ALIGN_CENTER
+        elif shapetype == SHAPETYPE_POLYGON:
+            halign = ALIGN_CENTER
+            valign = ALIGN_CENTER
+        elif shapetype == SHAPETYPE_ARC:
+            halign = ALIGN_LEFT
+            valign = ALIGN_CENTER
+        
+        return (x, y, halign, valign)
+
+
+
+if resource.has_gdal_support():
+    import gdal
+    from gdalconst import GA_ReadOnly
+
+class RasterLayer(BaseLayer):
+
+    MASK_NONE  = 0
+    MASK_BIT   = 1
+    MASK_ALPHA = 2
+
+    def __init__(self, title, filename, projection = None, 
+                 visible = True, opacity = 1, masktype = MASK_BIT):
+        """Initialize the Raster Layer.
+
+        title -- title for the layer.
+
+        filename -- file name of the source image.
+
+        projection -- Projection object describing the projection which
+                      the source image is in.
+
+        visible -- True is the layer should initially be visible.
+
+        Throws IOError if the filename is invalid or points to a file that
+        is not in a format GDAL can use.
+        """
+
+        BaseLayer.__init__(self, title, visible = visible)
+
+        self.projection = projection
+        self.filename = os.path.abspath(filename)
+
+        self.bbox = -1
+
+        self.mask_type = masktype
+        self.opacity = opacity
+
+        self.image_info = None
+
+        if resource.has_gdal_support():
+            #
+            # temporarily open the file so that GDAL can test if it's valid.
+            #
+            dataset = gdal.Open(self.filename, GA_ReadOnly)
+
+            if dataset is None:
+                raise IOError()
+
+            #
+            # while we have the file, extract some basic information 
+            # that we can display later
+            #
+            self.image_info = {}
+
+            self.image_info["nBands"] = dataset.RasterCount
+            self.image_info["Size"] = (dataset.RasterXSize, dataset.RasterYSize)
+            self.image_info["Driver"] = dataset.GetDriver().ShortName
+
+            # store some information about the individual bands
+            # [min_value, max_value]
+            a = self.image_info["BandData"] = []
+
+            for i in range(1, dataset.RasterCount+1):
+                band = dataset.GetRasterBand(i)
+                a.append(band.ComputeRasterMinMax())
+
+        self.UnsetModified()
+
+    def BoundingBox(self):
+        """Return the layer's bounding box in the intrinsic coordinate system.
+
+        If the there is no support for images, or the file cannot
+        be read, or there is no geographics information available, return None.
+        """
+        if not resource.has_gdal_support():
+            return None
+
+        if self.bbox == -1:
+            dataset = gdal.Open(self.filename, GA_ReadOnly)
+            if dataset is None:
+                self.bbox = None
+            else:
+                geotransform = dataset.GetGeoTransform()
+                if geotransform is None:
+                    return None
+
+                x = 0
+                y = dataset.RasterYSize
+                left = geotransform[0] +        \
+                       geotransform[1] * x +    \
+                       geotransform[2] * y
+
+                bottom = geotransform[3] +      \
+                         geotransform[4] * x +  \
+                         geotransform[5] * y
+
+                x = dataset.RasterXSize
+                y = 0
+                right = geotransform[0] +       \
+                        geotransform[1] * x +   \
+                        geotransform[2] * y
+
+                top = geotransform[3] +         \
+                      geotransform[4] * x +     \
+                      geotransform[5] * y
+
+                self.bbox = (left, bottom, right, top)
+
+        return self.bbox
+
+    def LatLongBoundingBox(self):
+        bbox = self.BoundingBox()
+        if bbox is None:
+            return None
+
+        if self.projection is not None:
+            bbox = self.projection.InverseBBox(bbox)
+
+        return bbox
+
+    def Type(self):
+        return "Image"
+
+    def GetImageFilename(self):
+        return self.filename
+
+    def MaskType(self):
+        """Return True if the mask should be used when rendering the layer."""
+        return self.mask_type
+
+    def SetMaskType(self, type):
+        """Set the type of mask to use.
+
+        type can be one of MASK_NONE, MASK_BIT, MASK_ALPHA
+
+        If the state changes, a LAYER_CHANGED message is sent.
+        """
+        if type not in (self.MASK_NONE, self.MASK_BIT, self.MASK_ALPHA):
+            raise ValueError("type is invalid")
+
+        if type != self.mask_type: 
+            self.mask_type = type
+            self.changed(LAYER_CHANGED, self)
+
+    def Opacity(self):
+        """Return the level of opacity used in alpha blending.
+        """
+        return self.opacity
+
+    def SetOpacity(self, op):
+        """Set the level of alpha opacity. 
+
+        0 <= op <= 1.
+
+        The layer is fully opaque when op = 1.
+        """
+        if not (0 <= op <= 1):
+            raise ValueError("op out of range")
+
+        if op != self.opacity: 
+            self.opacity = op
+            self.changed(LAYER_CHANGED, self)
+
+    def ImageInfo(self):
+        return self.image_info
+
+    def TreeInfo(self):
+        items = []
+
+        items.append(_("Filename: %s") % self.GetImageFilename())
+
+        if self.Visible():
+            items.append(_("Shown"))
+        else:
+            items.append(_("Hidden"))
+
+        bbox = self.LatLongBoundingBox()
+        if bbox is not None:
+            items.append(_("Extent (lat-lon): (%g, %g, %g, %g)") % bbox)
+        else:
+            items.append(_("Extent (lat-lon):"))
+
+        if self.projection and len(self.projection.params) > 0:
+            items.append((_("Projection"),
+                        [str(param) for param in self.projection.params]))
+
+        return (_("Layer '%s'") % self.Title(), items)
+

Added: packages/thuban/branches/upstream/current/Thuban/Model/load.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/load.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/load.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,696 @@
+# Copyright (C) 2001, 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+# Bernhard Herzog <bh at intevation.de>
+# Jonathan Coles <jonathan at intevation.de>
+# Frank Koormann <frank at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with GRASS for details.
+
+"""
+Parser for thuban session files.
+"""
+
+__version__ = "$Revision: 2688 $"
+
+import string, os
+
+import xml.sax
+import xml.sax.handler
+from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException
+
+from Thuban import _
+
+from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
+     FIELDTYPE_STRING
+
+from Thuban.Model.color import Color, Transparent
+
+from Thuban.Model.session import Session
+from Thuban.Model.map import Map
+from Thuban.Model.layer import Layer, RasterLayer
+from Thuban.Model.proj import Projection
+from Thuban.Model.range import Range
+from Thuban.Model.classification import Classification, \
+    ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, \
+    ClassGroupPattern, ClassGroupMap, \
+    ClassGroupProperties
+from Thuban.Model.data import DerivedShapeStore, ShapefileStore
+from Thuban.Model.table import DBFTable
+from Thuban.Model.transientdb import TransientJoinedTable
+
+from Thuban.Model.xmlreader import XMLReader
+import resource
+
+import postgisdb
+
+class LoadError(Exception):
+
+    """Exception raised when the thuban file is corrupted
+
+    Not all cases of corrupted thuban files will lead to this exception
+    but those that are found by checks in the loading code itself are. 
+    """
+
+
+class LoadCancelled(Exception):
+
+    """Exception raised to indicate that loading was interrupted by the user"""
+
+
+def parse_color(color):
+    """Return the color object for the string color.
+
+    Color may be either 'None' or of the form '#RRGGBB' in the usual
+    HTML color notation
+    """
+    color = string.strip(color)
+    if color == "None":
+        result = Transparent
+    elif color[0] == '#':
+        if len(color) == 7:
+            r = string.atoi(color[1:3], 16) / 255.0
+            g = string.atoi(color[3:5], 16) / 255.0
+            b = string.atoi(color[5:7], 16) / 255.0
+            result = Color(r, g, b)
+        else:
+            raise ValueError(_("Invalid hexadecimal color specification %s")
+                             % color)
+    else:
+        raise ValueError(_("Invalid color specification %s") % color)
+    return result
+
+class AttrDesc:
+
+    def __init__(self, name, required = False, default = "",
+                 conversion = None):
+        if not isinstance(name, tuple):
+            fullname = (None, name)
+        else:
+            fullname = name
+            name = name[1]
+        self.name = name
+        self.fullname = fullname
+        self.required = required
+        self.default = default
+        self.conversion = conversion
+
+        # set by the SessionLoader's check_attrs method
+        self.value = None
+
+
+class SessionLoader(XMLReader):
+
+    def __init__(self, db_connection_callback = None, 
+                       shapefile_callback = None):
+        """Inititialize the Sax handler."""
+        XMLReader.__init__(self)
+
+        self.db_connection_callback = db_connection_callback
+        self.shapefile_callback = shapefile_callback
+        self.theSession = None
+        self.aMap = None
+        self.aLayer = None
+
+        # Map ids used in the thuban file to the corresponding objects
+        # in the session
+        self.idmap = {}
+
+        dispatchers = {
+            'session'       : ("start_session",        "end_session"),
+
+            'dbconnection': ("start_dbconnection", None),
+
+            'dbshapesource': ("start_dbshapesource", None),
+            'fileshapesource': ("start_fileshapesource", None),
+            'derivedshapesource': ("start_derivedshapesource", None),
+            'filetable': ("start_filetable", None),
+            'jointable': ("start_jointable", None),
+
+            'map'           : ("start_map",            "end_map"),
+            'projection'    : ("start_projection",     "end_projection"),
+            'parameter'     : ("start_parameter",      None),
+            'layer'         : ("start_layer",          "end_layer"),
+            'rasterlayer'   : ("start_rasterlayer",    "end_rasterlayer"),
+            'classification': ("start_classification", "end_classification"),
+            'clnull'        : ("start_clnull",         "end_clnull"),
+            'clpoint'       : ("start_clpoint",        "end_clpoint"),
+            'clrange'       : ("start_clrange",        "end_clrange"),
+            'clpattern'     : ("start_clpattern",      "end_clpattern"),
+            'cldata'        : ("start_cldata",         "end_cldata"),
+            'table'         : ("start_table",          "end_table"),
+            'labellayer'    : ("start_labellayer",     None),
+            'label'         : ("start_label",          None)}
+
+        # all dispatchers should be used for the 0.8 and 0.9 namespaces too
+        for xmlns in ("http://thuban.intevation.org/dtds/thuban-0.8.dtd",
+                      "http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd",
+                      "http://thuban.intevation.org/dtds/thuban-0.9.dtd",
+                      "http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd",
+                      "http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd",
+                      "http://thuban.intevation.org/dtds/thuban-1.0.0.dtd",
+                      "http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"):
+            for key, value in dispatchers.items():
+                dispatchers[(xmlns, key)] = value
+
+        XMLReader.AddDispatchers(self, dispatchers)
+
+    def Destroy(self):
+        """Clear all instance variables to cut cyclic references.
+
+        The GC would have collected the loader eventually but it can
+	happen that it doesn't run at all until Thuban is closed (2.3
+	but not 2.2 tries a bit harder and forces a collection when the
+	interpreter terminates)
+        """
+        self.__dict__.clear()
+
+    def start_session(self, name, qname, attrs):
+        self.theSession = Session(self.encode(attrs.get((None, 'title'),
+                                                        None)))
+
+    def end_session(self, name, qname):
+        pass
+
+    def check_attrs(self, element, attrs, descr):
+        """Check and convert some of the attributes of an element
+
+        Parameters:
+           element -- The element name
+           attrs -- The attrs mapping as passed to the start_* methods
+           descr -- Sequence of attribute descriptions (AttrDesc instances)
+
+        Return a dictionary containig normalized versions of the
+        attributes described in descr. The keys of that dictionary are
+        the name attributes of the attribute descriptions. The attrs
+        dictionary will not be modified.
+
+        If the attribute is required, i.e. the 'required' attribute of
+        the descrtiption is true, but it is not in attrs, raise a
+        LoadError.
+
+        If the attribute has a default value and it is not present in
+        attrs, use that default value as the value in the returned dict.
+
+        The value is converted before putting it into the returned dict.
+        The following conversions are available:
+
+           'filename' -- The attribute is a filename.
+
+                         If the filename is a relative name, interpret
+                         it relative to the directory containing the
+                         .thuban file and make it an absolute name
+
+           'shapestore' -- The attribute is the ID of a shapestore
+                           defined earlier in the .thuban file. Look it
+                           up self.idmap
+
+           'table' -- The attribute is the ID of a table or shapestore
+                      defined earlier in the .thuban file. Look it up
+                      self.idmap. If it's the ID of a shapestore the
+                      value will be the table of the shapestore.
+
+           'idref' -- The attribute is the id of an object defined
+                      earlier in the .thuban file. Look it up self.idmap
+
+           'ascii' -- The attribute is converted to a bytestring with
+                      ascii encoding.
+
+           a callable -- The attribute value is passed to the callable
+                         and the return value is used as the converted
+                         value
+
+        If no conversion is specified for an attribute it is converted
+        with self.encode.
+        """
+        normalized = {}
+
+        for d in descr:
+            if d.required and not attrs.has_key(d.fullname):
+                raise LoadError("Element %s requires an attribute %r"
+                                % (element, d.name))
+            value = attrs.get(d.fullname, d.default)
+
+            if d.conversion in ("idref", "shapesource"):
+                if value in self.idmap:
+                    value = self.idmap[value]
+                else:
+                    raise LoadError("Element %s requires an already defined ID"
+                                    " in attribute %r"
+                                    % (element, d.name))
+            elif d.conversion == "table":
+                if value in self.idmap:
+                    value = self.idmap[value]
+                    if isinstance(value, ShapefileStore):
+                        value = value.Table()
+                else:
+                    raise LoadError("Element %s requires an already defined ID"
+                                    " in attribute %r"
+                                    % (element, d.name))
+            elif d.conversion == "filename":
+                value = os.path.abspath(os.path.join(self.GetDirectory(),
+                                                     self.encode(value)))
+            elif d.conversion == "ascii":
+                value = value.encode("ascii")
+            elif d.conversion:
+                # Assume it's a callable
+                value = d.conversion(value)
+            else:
+               value = self.encode(value)
+
+            normalized[d.name] = value
+        return normalized
+
+    def open_shapefile(self, filename):
+        """Open shapefile, with alternative path handling.
+         
+           If a shapefile cannot be opened and an IOError is raised, check for
+           an alternative. This alternative can be specified interactively by
+           the user or taken from a list of (potential) locations, depending on
+           the callback implementation.
+            
+           The alternative is rechecked. If taken from a list the user
+           has to confirm the alternative.
+        """
+
+        # Flag if the alternative path was specified interactively / from list.
+        from_list = 0
+        while 1:
+            try: 
+                store = self.theSession.OpenShapefile(filename)
+                if from_list:
+                    # A valid path has been guessed from a list
+                    # Let the user confirm - or select an alternative.
+                    filename, from_list = self.shapefile_callback(
+                                            filename, "check")
+                    if filename is None:
+                        # Selection cancelled
+                        raise LoadCancelled
+                    elif store.FileName() == filename:
+                        # Proposed file has been accepted
+                        break
+                    else:
+                        # the filename has been changed, try the new file
+                        pass
+                else:
+                    break
+            except IOError:
+                if self.shapefile_callback is not None:
+                    filename, from_list = self.shapefile_callback(
+                                            filename, 
+                                            mode = "search", 
+                                            second_try = from_list)
+                    if filename is None:
+                        raise LoadCancelled
+                else:
+                    raise
+        return store
+
+    def start_dbconnection(self, name, qname, attrs):
+        attrs = self.check_attrs(name, attrs,
+                                 [AttrDesc("id", True),
+                                  AttrDesc("dbtype", True),
+                                  AttrDesc("host", False, ""),
+                                  AttrDesc("port", False, ""),
+                                  AttrDesc("user", False, ""),
+                                  AttrDesc("dbname", True)])
+        ID = attrs["id"]
+        dbtype = attrs["dbtype"]
+        if dbtype != "postgis":
+            raise LoadError("dbtype %r not supported" % filetype)
+
+        del attrs["id"]
+        del attrs["dbtype"]
+
+        # Try to open the connection and if it fails ask the user for
+        # the correct parameters repeatedly.
+        # FIXME: it would be better not to insist on getting a
+        # connection here. We should handle this more like the raster
+        # images where the layers etc still are created but are not
+        # drawn in case Thuban can't use the data for various reasons
+        while 1:
+            try:
+                conn = postgisdb.PostGISConnection(**attrs)
+                break
+            except postgisdb.ConnectionError, val:
+                if self.db_connection_callback is not None:
+                    attrs = self.db_connection_callback(attrs, str(val))
+                    if attrs is None:
+                        raise LoadCancelled
+                else:
+                    raise
+
+        self.idmap[ID] = conn
+        self.theSession.AddDBConnection(conn)
+
+    def start_dbshapesource(self, name, qname, attrs):
+        attrs = self.check_attrs(name, attrs,
+                                 [AttrDesc("id", True),
+                                  AttrDesc("dbconn", True,
+                                           conversion = "idref"),
+                                  AttrDesc("tablename", True,
+                                           conversion = "ascii"),
+                                  # id_column and geometry_column were
+                                  # newly introduced with thuban-1.1.dtd
+                                  # where they're required.  Since we
+                                  # support the older formats too we
+                                  # have them optional here.
+                                  AttrDesc("id_column", False, "gid",
+                                           conversion = "ascii"),
+                                  AttrDesc("geometry_column", False,
+                                           conversion = "ascii")])
+        # The default value of geometry_column to use when instantiating
+        # the db shapestore is None which we currently can't easily use
+        # in check_attrs
+        geometry_column = attrs["geometry_column"]
+        if not geometry_column:
+            geometry_column = None
+        dbopen = self.theSession.OpenDBShapeStore
+        self.idmap[attrs["id"]] = dbopen(attrs["dbconn"], attrs["tablename"],
+                                         id_column = attrs["id_column"],
+                                         geometry_column=geometry_column)
+
+    def start_fileshapesource(self, name, qname, attrs):
+        attrs = self.check_attrs(name, attrs,
+                                  [AttrDesc("id", True),
+                                   AttrDesc("filename", True,
+                                            conversion = "filename"),
+                                   AttrDesc("filetype", True)])
+        ID = attrs["id"]
+        filename = attrs["filename"]
+        filetype = attrs["filetype"]
+        if filetype != "shapefile":
+            raise LoadError("shapesource filetype %r not supported" % filetype)
+        self.idmap[ID] = self.open_shapefile(filename)
+
+    def start_derivedshapesource(self, name, qname, attrs):
+        attrs = self.check_attrs(name, attrs,
+                                 [AttrDesc("id", True),
+                                  AttrDesc("shapesource", True,
+                                           conversion = "shapesource"),
+                                  AttrDesc("table", True, conversion="table")])
+        store = DerivedShapeStore(attrs["shapesource"], attrs["table"])
+        self.theSession.AddShapeStore(store)
+        self.idmap[attrs["id"]] = store
+
+    def start_filetable(self, name, qname, attrs):
+        attrs = self.check_attrs(name, attrs,
+                                 [AttrDesc("id", True),
+                                  AttrDesc("title", True),
+                                  AttrDesc("filename", True,
+                                           conversion = "filename"),
+                                  AttrDesc("filetype")])
+        filetype = attrs["filetype"]
+        if filetype != "DBF":
+            raise LoadError("shapesource filetype %r not supported" % filetype)
+        table = DBFTable(attrs["filename"])
+        table.SetTitle(attrs["title"])
+        self.idmap[attrs["id"]] = self.theSession.AddTable(table)
+
+    def start_jointable(self, name, qname, attrs):
+        attrs = self.check_attrs(name, attrs,
+                                 [AttrDesc("id", True),
+                                  AttrDesc("title", True),
+                                  AttrDesc("left", True, conversion="table"),
+                                  AttrDesc("leftcolumn", True),
+                                  AttrDesc("right", True, conversion="table"),
+                                  AttrDesc("rightcolumn", True),
+
+                                  # jointype is required for file
+                                  # version 0.9 but this attribute
+                                  # wasn't in the 0.8 version because of
+                                  # an oversight so we assume it's
+                                  # optional since we want to handle
+                                  # both file format versions here.
+                                  AttrDesc("jointype", False,
+                                           default="INNER")])
+
+        jointype = attrs["jointype"]
+        if jointype == "LEFT OUTER":
+            outer_join = True
+        elif jointype == "INNER":
+            outer_join = False
+        else:
+            raise LoadError("jointype %r not supported" % jointype )
+        table = TransientJoinedTable(self.theSession.TransientDB(),
+                                     attrs["left"], attrs["leftcolumn"],
+                                     attrs["right"], attrs["rightcolumn"],
+                                     outer_join = outer_join)
+        table.SetTitle(attrs["title"])
+        self.idmap[attrs["id"]] = self.theSession.AddTable(table)
+
+    def start_map(self, name, qname, attrs):
+        """Start a map."""
+        self.aMap = Map(self.encode(attrs.get((None, 'title'), None)))
+
+    def end_map(self, name, qname):
+        self.theSession.AddMap(self.aMap)
+        self.aMap = None
+
+    def start_projection(self, name, qname, attrs):
+        attrs = self.check_attrs(name, attrs,
+                                 [AttrDesc("name", conversion=self.encode),
+                                  AttrDesc("epsg", default=None,
+                                           conversion=self.encode)])
+        self.projection_name = attrs["name"]
+        self.projection_epsg = attrs["epsg"]
+        self.projection_params = [ ]
+
+    def end_projection(self, name, qname):
+        if self.aLayer is not None:
+            obj = self.aLayer
+        elif self.aMap is not None:
+            obj = self.aMap
+        else:
+            assert False, "projection tag out of context"
+            pass
+
+        obj.SetProjection(Projection(self.projection_params,
+                                     self.projection_name,
+                                     epsg = self.projection_epsg))
+
+    def start_parameter(self, name, qname, attrs):
+        s = attrs.get((None, 'value'))
+        s = str(s) # we can't handle unicode in proj
+        self.projection_params.append(s)
+
+    def start_layer(self, name, qname, attrs, layer_class = Layer):
+        """Start a layer
+
+        Instantiate a layer of class layer_class from the attributes in
+        attrs which may be a dictionary as well as the normal SAX attrs
+        object and bind it to self.aLayer.
+        """
+        title = self.encode(attrs.get((None, 'title'), ""))
+        filename = attrs.get((None, 'filename'), "")
+        filename = os.path.join(self.GetDirectory(), filename)
+        filename = self.encode(filename)
+        visible  = self.encode(attrs.get((None, 'visible'), "true")) != "false"
+        fill = parse_color(attrs.get((None, 'fill'), "None"))
+        stroke = parse_color(attrs.get((None, 'stroke'), "#000000"))
+        stroke_width = int(attrs.get((None, 'stroke_width'), "1"))
+        if attrs.has_key((None, "shapestore")):
+            store = self.idmap[attrs[(None, "shapestore")]]
+        else:
+            store = self.open_shapefile(filename)
+
+        self.aLayer = layer_class(title, store,
+                                  fill = fill, stroke = stroke,
+                                  lineWidth = stroke_width,
+                                  visible = visible)
+
+    def end_layer(self, name, qname):
+        self.aMap.AddLayer(self.aLayer)
+        self.aLayer = None
+
+    def start_rasterlayer(self, name, qname, attrs, layer_class = RasterLayer):
+        title = self.encode(attrs.get((None, 'title'), ""))
+        filename = attrs.get((None, 'filename'), "")
+        filename = os.path.join(self.GetDirectory(), filename)
+        filename = self.encode(filename)
+        visible  = self.encode(attrs.get((None, 'visible'), "true")) != "false"
+        opacity  = float(attrs.get((None, 'opacity'), "1"))
+        masktype = str(attrs.get((None, 'masktype'), "bit"))
+
+        masktypes = {"none": layer_class.MASK_NONE,
+                     "bit":  layer_class.MASK_BIT,
+                     "alpha": layer_class.MASK_ALPHA}
+
+        self.aLayer = layer_class(title, filename, 
+                                  visible = visible,
+                                  opacity = opacity,
+                                  masktype = masktypes[masktype])
+
+    def end_rasterlayer(self, name, qname):
+        self.aMap.AddLayer(self.aLayer)
+        self.aLayer = None
+
+    def start_classification(self, name, qname, attrs):
+    	# field and field_type are optional because the classification
+	# can also be empty, ie. have only a default.
+        attrs = self.check_attrs(name, attrs,
+                                 [AttrDesc("field", False),
+                                  AttrDesc("field_type", False)])
+
+        field = attrs["field"]
+        fieldType = attrs["field_type"]
+
+	if field == "": return # no need to set classification column.
+
+        dbFieldType = self.aLayer.GetFieldType(field)
+
+        if fieldType != dbFieldType:
+            raise ValueError(_("xml field type differs from database!"))
+
+        # setup conversion routines depending on the kind of data
+        # we will be seeing later on
+        if fieldType == FIELDTYPE_STRING:
+            self.conv = str
+        elif fieldType == FIELDTYPE_INT:
+            self.conv = lambda p: int(float(p))
+        elif fieldType == FIELDTYPE_DOUBLE:
+            self.conv = float
+
+        self.aLayer.SetClassificationColumn(field)
+
+    def end_classification(self, name, qname): 
+        pass
+
+    def start_clnull(self, name, qname, attrs):
+        self.cl_group = ClassGroupDefault()
+        self.cl_group.SetLabel(self.encode(attrs.get((None, 'label'), "")))
+        self.cl_prop = ClassGroupProperties()
+
+    def end_clnull(self, name, qname):
+        self.cl_group.SetProperties(self.cl_prop)
+        self.aLayer.GetClassification().SetDefaultGroup(self.cl_group)
+        del self.cl_group, self.cl_prop
+
+    def start_clpoint(self, name, qname, attrs):
+        attrib_value = attrs.get((None, 'value'), "0")
+
+        field = self.aLayer.GetClassificationColumn()
+        if self.aLayer.GetFieldType(field) == FIELDTYPE_STRING:
+            value = self.encode(attrib_value)
+        else:
+            value = self.conv(attrib_value)
+        self.cl_group = ClassGroupSingleton(value)
+        self.cl_group.SetLabel(self.encode(attrs.get((None, 'label'), "")))
+        self.cl_prop = ClassGroupProperties()
+
+
+    def end_clpoint(self, name, qname):
+        self.cl_group.SetProperties(self.cl_prop)
+        self.aLayer.GetClassification().AppendGroup(self.cl_group)
+        del self.cl_group, self.cl_prop
+
+    def start_clrange(self, name, qname, attrs):
+        attrs = self.check_attrs(name, attrs,
+                                 [AttrDesc("range", False, None),
+                                  AttrDesc("min", False, None),
+                                  AttrDesc("max", False, None)])
+
+        range = attrs['range']
+        # for backward compatibility (min/max are not saved)
+        min   = attrs['min']
+        max   = attrs['max']
+
+        try:
+            if range is not None:
+                self.cl_group = ClassGroupRange(Range(range))
+            elif min is not None and max is not None:
+                self.cl_group = ClassGroupRange((self.conv(min), 
+                                                 self.conv(max)))
+            else:
+                self.cl_group = ClassGroupRange(Range(None))
+
+        except ValueError:
+            raise ValueError(_("Classification range is not a number!"))
+
+        self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
+        self.cl_prop = ClassGroupProperties()
+
+
+    def end_clrange(self, name, qname):
+        self.cl_group.SetProperties(self.cl_prop)
+        self.aLayer.GetClassification().AppendGroup(self.cl_group)
+        del self.cl_group, self.cl_prop
+
+
+    def start_clpattern(self, name, qname, attrs):
+        pattern = attrs.get((None, 'pattern'), "")
+
+        self.cl_group = ClassGroupPattern(self.encode(pattern))
+        self.cl_group.SetLabel(self.encode(attrs.get((None, 'label'), "")))
+        self.cl_prop = ClassGroupProperties()
+
+    def end_clpattern(self, name, qname):
+        self.cl_group.SetProperties(self.cl_prop)
+        self.aLayer.GetClassification().AppendGroup(self.cl_group)
+        del self.cl_group, self.cl_prop
+
+
+    def start_cldata(self, name, qname, attrs):
+        self.cl_prop.SetLineColor(
+            parse_color(attrs.get((None, 'stroke'), "None")))
+        self.cl_prop.SetLineWidth(
+            int(attrs.get((None, 'stroke_width'), "0")))
+        self.cl_prop.SetSize(int(attrs.get((None, 'size'), "5")))
+        self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))
+
+    def end_cldata(self, name, qname):
+        pass
+
+    def start_labellayer(self, name, qname, attrs):
+        self.aLayer = self.aMap.LabelLayer()
+
+    def start_label(self, name, qname, attrs):
+        attrs = self.check_attrs(name, attrs,
+                                 [AttrDesc("x", True, conversion = float),
+                                  AttrDesc("y", True, conversion = float),
+                                  AttrDesc("text", True),
+                                  AttrDesc("halign", True,
+                                           conversion = "ascii"),
+                                  AttrDesc("valign", True,
+                                           conversion = "ascii")])
+        x = attrs['x']
+        y = attrs['y']
+        text = attrs['text']
+        halign = attrs['halign']
+        valign = attrs['valign']
+        if halign not in ("left", "center", "right"):
+            raise LoadError("Unsupported halign value %r" % halign)
+        if valign not in ("top", "center", "bottom"):
+            raise LoadError("Unsupported valign value %r" % valign)
+        self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
+
+    def characters(self, chars):
+        pass
+
+
+def load_session(filename, db_connection_callback = None, 
+                           shapefile_callback = None):
+    """Load a Thuban session from the file object file
+
+    The db_connection_callback, if given should be a callable object
+    that can be called like this:
+       db_connection_callback(params, message)
+
+    where params is a dictionary containing the known connection
+    parameters and message is a string with a message why the connection
+    failed. db_connection_callback should return a new dictionary with
+    corrected and perhaps additional parameters like a password or None
+    to indicate that the user cancelled.
+    """
+    handler = SessionLoader(db_connection_callback, shapefile_callback)
+    handler.read(filename)
+
+    session = handler.theSession
+    # Newly loaded session aren't modified
+    session.UnsetModified()
+
+    handler.Destroy()
+
+    return session
+

Added: packages/thuban/branches/upstream/current/Thuban/Model/map.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/map.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/map.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,301 @@
+# Copyright (c) 2001-2003, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2569 $"
+
+from messages import MAP_LAYERS_CHANGED, MAP_PROJECTION_CHANGED, \
+     CHANGED, LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \
+     LAYER_VISIBILITY_CHANGED, LAYER_CHANGED, MAP_STACKING_CHANGED, \
+     MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED
+
+from Thuban import _
+
+from base import TitledObject, Modifiable
+
+from label import LabelLayer
+
+
+class Map(TitledObject, Modifiable):
+
+    """Represent a map.
+
+    A map is a list of layers. Additionally
+    there is a special label layer containing all labels that
+    are defined for the map.
+
+    Map objects send the following message types:
+
+        TITLE_CHANGED -- The title has changed. Parameter: the map.
+
+        MAP_LAYERS_CHANGED -- Layers were added, removed or rearranged.
+                        Parameters: the map
+
+        MAP_PROJECTION_CHANGED -- the map's projection has changed.
+                        Parameter: the map
+    """
+
+    forwarded_channels = (CHANGED,
+                          LAYER_PROJECTION_CHANGED,
+                          LAYER_LEGEND_CHANGED,
+                          LAYER_CHANGED,
+                          LAYER_VISIBILITY_CHANGED)
+
+    def __init__(self, title, projection = None):
+        """Initialize the map."""
+        TitledObject.__init__(self, title)
+        Modifiable.__init__(self)
+        self.layers = []
+        self.label_layer = LabelLayer(_("Labels"))
+        self.label_layer.Subscribe(CHANGED, self.forward, MAP_LAYERS_CHANGED)
+        self.projection = projection
+
+    def Destroy(self):
+        """Destroys the map object with all layers including the label layer.
+
+        Calls Modifiable. Destroy first since it will call
+        Publisher.Destroy which removes all subscriptions. Otherwise
+        clearing the layers results in messages to be sent which can
+        cause problems.
+        """
+        Modifiable.Destroy(self)
+        self.ClearLayers()
+        self.label_layer.Unsubscribe(CHANGED, self.forward, MAP_LAYERS_CHANGED)
+        self.label_layer.Destroy()
+
+    def AddLayer(self, layer):
+        """Append layer to the map on top of all."""
+        self.layers.append(layer)
+        self.subscribe_layer_channels(layer)
+        self.changed(MAP_LAYERS_CHANGED, self)
+        self.changed(MAP_LAYERS_ADDED, self)
+
+    def RemoveLayer(self, layer):
+        """Remove layer from the map.
+
+        This can not be applied for the label layer of the map.
+        """
+        self.unsubscribe_layer_channels(layer)
+        self.layers.remove(layer)
+        self.changed(MAP_LAYERS_CHANGED, self)
+        self.changed(MAP_LAYERS_REMOVED, self)
+        layer.Destroy()
+
+    def CanRemoveLayer(self, layer):
+        """Return true if the layer can be deleted.
+
+        The default implementation always returns 1. Derived classes
+        should override this method if they have e.g. special layers
+        that the user should not be able to remove.
+        """
+        return 1
+
+    def ClearLayers(self):
+        """Delete all layers and also remove all labels from the label layer.
+        """
+        for layer in self.layers:
+            self.unsubscribe_layer_channels(layer)
+            layer.Destroy()
+        del self.layers[:]
+        self.label_layer.ClearLabels()
+        self.changed(MAP_LAYERS_CHANGED, self)
+        self.changed(MAP_LAYERS_REMOVED, self)
+
+    def subscribe_layer_channels(self, layer):
+        """Subscribe to some of layer's channels."""
+        for channel in self.forwarded_channels:
+            layer.Subscribe(channel, self.forward, channel)
+
+    def unsubscribe_layer_channels(self, layer):
+        """Unsubscribe to some of layer's channels."""
+        for channel in self.forwarded_channels:
+            layer.Unsubscribe(channel, self.forward, channel)
+
+    def LabelLayer(self):
+        """Return the Map's label layer"""
+        return self.label_layer
+
+    def Layers(self):
+        """Return the list of layers contained in the map.
+
+        The list does not include the label layer which
+        can be retrieved by a separate method."""
+        return self.layers
+
+    def HasLayers(self):
+        """Information whether this map has layers.
+
+        Returns true if the map has at least one layer other
+        than the label layer."""
+        return len(self.layers) > 0
+
+    def MoveLayerToTop(self, layer):
+        """Put the layer on top of the layer stack.
+
+        This can not be applied to the label layer.
+
+        If the layer is already at the top do nothing. If the stacking
+        order has been changed, issue a MAP_LAYERS_CHANGED message.
+        """
+        index = self.layers.index(layer)
+        if index < len(self.layers) - 1:
+            del self.layers[index]
+            self.layers.append(layer)
+            self.changed(MAP_LAYERS_CHANGED, self)
+            self.changed(MAP_STACKING_CHANGED, self)
+
+    def RaiseLayer(self, layer):
+        """Swap the layer with the one above it.
+
+        This does not apply to the label layer.
+
+        If the layer is already at the top do nothing. If the stacking
+        order has been changed, issue a MAP_LAYERS_CHANGED message.
+        """
+        index = self.layers.index(layer)
+        if index < len(self.layers) - 1:
+            del self.layers[index]
+            self.layers.insert(index + 1, layer)
+            self.changed(MAP_LAYERS_CHANGED, self)
+            self.changed(MAP_STACKING_CHANGED, self)
+
+    def LowerLayer(self, layer):
+        """Swap the layer with the one below it.
+
+        This does not apply to the label layer.
+
+        If the layer is already at the bottom do nothing. If the
+        stacking order has been changed, issue a MAP_LAYERS_CHANGED message.
+        """
+        index = self.layers.index(layer)
+        if index > 0:
+            del self.layers[index]
+            self.layers.insert(index - 1, layer)
+            self.changed(MAP_LAYERS_CHANGED, self)
+            self.changed(MAP_STACKING_CHANGED, self)
+
+    def MoveLayerToBottom(self, layer):
+        """Put the layer at the bottom of the stack.
+
+        This does not apply to the label layer.
+
+        If the layer is already at the bottom do nothing. If the
+        stacking order has been changed, issue a MAP_LAYERS_CHANGED message.
+        """
+        index = self.layers.index(layer)
+        if index > 0:
+            del self.layers[index]
+            self.layers.insert(0, layer)
+            self.changed(MAP_LAYERS_CHANGED, self)
+            self.changed(MAP_STACKING_CHANGED, self)
+
+    def BoundingBox(self):
+        """Return the bounding box of the map in Lat/Lon coordinates.
+
+        The label layer is not considered for the computation of the
+        bounding box.
+
+        Return None if there are no layers (except the label layer) or
+        no layer contains any shapes.
+        """
+        if not self.layers:
+            return None
+        llx = []
+        lly = []
+        urx = []
+        ury = []
+        for layer in self.layers:
+            # the layer's bbox may be None if it doesn't have any shapes
+            bbox = layer.LatLongBoundingBox()
+            if bbox is not None:
+                left, bottom, right, top = bbox
+                llx.append(left)
+                lly.append(bottom)
+                urx.append(right)
+                ury.append(top)
+
+        # check whether there were any empty layers.
+        if llx:
+            return (min(llx), min(lly), max(urx), max(ury))
+        else:
+            return None
+
+    def ProjectedBoundingBox(self):
+        """Return the bounding box of the map in projected coordinates.
+
+        The label layer is not considered for the computation of the
+        bounding box.
+
+        Return None if there are no layers (except the label layer) or
+        no layer contains any shapes.
+        """
+        # This simply returns the rectangle given by the projected
+        # corners of the non-projected bbox.
+        bbox = self.BoundingBox()
+        if bbox is not None and self.projection is not None:
+            bbox = self.projection.ForwardBBox(bbox)
+        return bbox
+
+    def GetProjection(self):
+        """Return the projection of the map."""
+        return self.projection
+
+    def SetProjection(self, projection):
+        """Set the projection of the map.
+
+        Issue a MAP_PROJECTION_CHANGED message.
+        """
+        old_proj = self.projection
+        self.projection = projection
+        self.changed(MAP_PROJECTION_CHANGED, self, old_proj)
+
+    def forward(self, *args):
+        """Reissue events"""
+        if len(args) > 1:
+            args = (args[-1],) + args[:-1]
+        apply(self.issue, args)
+
+    def WasModified(self):
+        """Return true if the map or one of the layers was modified"""
+        if self.modified:
+            return 1
+        else:
+            for layer in self.layers:
+                if layer.WasModified():
+                    return 1
+            return self.label_layer.WasModified()
+
+    def UnsetModified(self):
+        """Unset the modified flag of the map and the layers"""
+        Modifiable.UnsetModified(self)
+        for layer in self.layers:
+            layer.UnsetModified()
+        self.label_layer.UnsetModified()
+
+    def TreeInfo(self):
+        """Return a description of the object.
+
+        A tuple of (title, tupel) describing the contents
+        of the object in a tree-structure is returned.
+        """
+        items = []
+        if self.BoundingBox() != None:
+            items.append(_("Extent (lat-lon): (%g, %g, %g, %g)")
+                         % self.BoundingBox())
+            if self.projection and len(self.projection.params) > 0:
+                items.append(_("Extent (projected): (%g, %g, %g, %g)")
+                             % self.ProjectedBoundingBox())
+                items.append((_("Projection"),
+                              [str(param)
+                               for param in self.projection.params]))
+
+        layers = self.layers[:]
+        layers.reverse()
+        items.extend(layers)
+        items.append(self.label_layer)
+
+        return (_("Map: %s") % self.title, items)

Added: packages/thuban/branches/upstream/current/Thuban/Model/messages.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/messages.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/messages.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,53 @@
+# Copyright (c) 2001, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Define the message types used by the classes implementing Thuban's data
+model. The messages types are simply strings. The message system itself
+is implemented in Thuban.Lib.connector.
+"""
+__version__ = "$Revision: 1823 $"
+
+# Common message types
+TITLE_CHANGED = "TITLE_CHANGED"
+CHANGED = "CHANGED"
+
+# ProjFile message types
+PROJECTION_ADDED = "PROJECTION_ADDED"
+PROJECTION_REPLACED = "PROJECTION_REPLACED"
+PROJECTION_REMOVED = "PROJECTION_REMOVED"
+
+# classification specific message types
+CLASS_CHANGED = "CLASS_CHANGED"
+
+# layer specific message types
+LAYER_PROJECTION_CHANGED = "LAYER_PROJECTION_CHANGED"
+LAYER_LEGEND_CHANGED = "LAYER_LEGEND_CHANGED"
+LAYER_VISIBILITY_CHANGED = "LAYER_VISIBILITY_CHANGED"
+LAYER_CHANGED = "LAYER_CHANGED"
+LAYER_SHAPESTORE_REPLACED = "LAYER_SHAPESTORE_REPLACED"
+
+# Map specific message types
+MAP_STACKING_CHANGED = "MAP_STACKING_CHANGED"
+MAP_LAYERS_CHANGED = "MAP_LAYERS_CHANGED"
+MAP_LAYERS_ADDED = "MAP_LAYERS_ADDED"
+MAP_LAYERS_REMOVED = "MAP_LAYERS_REMOVED"
+MAP_PROJECTION_CHANGED = "MAP_PROJECTION_CHANGED"
+
+# Extension specific message types
+EXTENSION_CHANGED = "EXTENSION_CHANGED"
+EXTENSION_OBJECTS_CHANGED = "EXTENSION_OBJECTS_CHANGED"
+
+# Session specific message types
+MAPS_CHANGED = "MAPS_CHANGED"
+EXTENSIONS_CHANGED = "EXTENSIONS_CHANGED"
+FILENAME_CHANGED = "FILENAME_CHANGED"
+
+TABLE_REMOVED = "TABLE_REMOVED"
+
+DBCONN_ADDED = "DBCONN_ADDED"
+DBCONN_REMOVED = "DBCONN_REMOVED"

Added: packages/thuban/branches/upstream/current/Thuban/Model/postgisdb.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/postgisdb.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/postgisdb.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,700 @@
+# Copyright (C) 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Martin Mueller <mmueller at intevation.de>
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Basic interface to a PostGIS database"""
+
+from __future__ import generators
+
+try:
+    import psycopg
+except ImportError:
+    psycopg = None
+
+import table
+import wellknowntext
+
+from data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT, RAW_WKT
+
+def has_postgis_support():
+    """Return whether this Thuban instance supports PostGIS connections
+
+    Having PostGIS support means that the psycopg module can be
+    imported.
+    """
+    return psycopg is not None
+
+def psycopg_version():
+    return psycopg.__version__
+
+if psycopg is not None:
+    # type_map maps psycopg type objects.  It's a list of pairs since
+    # the psycopg type objects are unhashable.
+    type_map = [(psycopg.STRING, table.FIELDTYPE_STRING),
+                (psycopg.INTEGER, table.FIELDTYPE_INT),
+                (psycopg.ROWID, table.FIELDTYPE_INT),
+                (psycopg.FLOAT, table.FIELDTYPE_DOUBLE)]
+
+    # _raw_type_map maps the postgresql type constants to Thuban type
+    # constants.  This is very low level and postgresql specific and
+    # should be used only when necessary.
+    _raw_type_map = {}
+    def _fill_raw_type_map():
+        for psycopg_type, thuban_type in type_map:
+            for value in psycopg_type.values:
+                _raw_type_map[value] = thuban_type
+    _fill_raw_type_map()
+
+
+def quote_identifier(ident):
+    """Return a quoted version of the identifier ident.
+
+    The return value is a string that can be put directly into an SQL
+    statement.  The quoted identifier is surrounded by double quotes and
+    any double quotes already in the input value are converted to two
+    double quotes.  Examples:
+
+    >>> quote_identifier("abc\"def")
+    '"abc""def"'
+    >>> quote_identifier("abc def")
+    '"abc def"'
+    """
+    return '"' + '""'.join(ident.split('"')) + '"'
+
+
+class ConnectionError(Exception):
+
+    """Class for exceptions occurring when establishing a Databse connection"""
+
+
+class PostGISConnection:
+
+    """Represent a PostGIS database
+
+    A PostGISConnection instance has the following public attributes:
+
+    dbname -- The name of the database
+    host, port -- Host and port to connect to
+    user -- The user name to connect as.
+
+    All of these attributes are strings and may be empty strings to
+    indicate default values.
+    """
+
+    def __init__(self, dbname, host="", user="", password="", dbtype="",
+                 port=""):
+        self.dbname = dbname
+        self.host = host
+        self.port = port
+        self.user = user
+        self.password = password
+        self.dbtype = dbtype
+        self.connect()
+
+    def connect(self):
+        """Internal: Establish the database connection"""
+        params = []
+        for name in ("host", "port", "dbname", "user", "password"):
+            val = getattr(self, name)
+            if val:
+                params.append("%s=%s" % (name, val))
+        try:
+            self.connection = psycopg.connect(" ".join(params))
+        except psycopg.OperationalError, val:
+            raise ConnectionError(str(val))
+
+        # Use autocommit mode.  For simple reading of the database it's
+        # sufficient and we don't have to care much about error
+        # handling.  Without autocommit, an errors during a cursor's
+        # execute method requires a rollback on the connection,
+        # otherwise later queries with the same or other cursors sharing
+        # the same connection will lead to further errors ("ERROR:
+        # current transaction is aborted, commands ignored until end of
+        # transaction block")
+        self.connection.autocommit()
+
+        # determine the OID for the geometry type. This is PostGIS
+        # specific.
+        cursor = self.connection.cursor()
+        cursor.execute("SELECT OID, typname FROM pg_type WHERE"
+                       +" typname = 'geometry'")
+        row = cursor.fetchone()
+        self.connection.commit()
+        if row is not None:
+            self.geometry_type = row[0]
+        else:
+            raise ValueError("Can't determine postgres type of geometries")
+
+    def BriefDescription(self):
+        """Return a brief, one-line description of the connection
+
+        The return value is suitable for a list box of all database
+        connections.
+        """
+        return ("postgis://%(user)s@%(host)s:%(port)s/%(dbname)s"
+                % self.__dict__)
+
+    def MatchesParameters(self, parameters):
+        """Return whether the connection matches the dictionary of parameters
+
+        Return whether instatiating the connection with the given
+        parameters would establish essentially the same connection as
+        self. The connection is essentially the same if the same
+        database (identified by host, port and databasename) is accessed
+        as the same user.
+        """
+        return (parameters["host"] == self.host
+                and parameters["port"] == self.port
+                and parameters["dbname"] == self.dbname
+                and parameters["user"] == self.user)
+
+    def Close(self):
+        """Close the database connection"""
+        self.connection.close()
+
+    def GeometryTables(self):
+        """Return a list with the names of all tables with a geometry column"""
+
+        # The query is basically taken from the psql v. 7.2.1.  When
+        # started with -E it prints the queries used for internal
+        # commands such as \d, which does mostly what we need here.
+        cursor = self.connection.cursor()
+        cursor.execute("SELECT c.relname FROM pg_class c"
+                       " WHERE c.relkind IN ('r', 'v')"
+                             # Omit the system tables
+                             " AND c.relname !~ '^pg_'"
+                             # Omit the special PostGIS tables
+                             " AND c.relname NOT IN ('geometry_columns',"
+                                                   " 'spatial_ref_sys')"
+                            " AND %d in (SELECT a.atttypid FROM pg_attribute a"
+                                       " WHERE a.attrelid = c.oid)"
+                       " ORDER BY c.relname;", (self.geometry_type,))
+        result = [row[0] for row in cursor.fetchall()]
+        self.connection.commit()
+        return result
+
+    def table_columns(self, tablename):
+        """Experimental: return information about the columns of a table
+
+        Return value is a list of (name, type) pairs where name is the
+        name of the column and type either one of the field type columns
+        or the string 'geometry' indicating a geometry column.
+
+        The intended use of this method is for table selection dialogs
+        which need to determine which columns are usable as id or
+        geometry columns respectively.  Suitable id columns will have
+        type FIELDTYPE_INT and geometry columns will have 'geometry'.
+        """
+        result = []
+        cursor = self.connection.cursor()
+
+        # This query is taken basically from the \d command of psql
+        # 7.2.1
+        cursor.execute("SELECT a.attname, a.atttypid, a.attnum"
+                       " FROM pg_class c, pg_attribute a"
+                            " WHERE c.relname = %s AND a.attrelid = c.oid"
+                       " ORDER BY a.attnum;", (tablename,))
+
+        for row in cursor.fetchall():
+            col_name, col_type, col_attnum = row
+            col = None
+            if col_attnum < 1:
+                # It's a system column.  Only the OID is interesting
+                # here
+                if col_name == "oid":
+                    col = (col_name, _raw_type_map[col_type])
+            else:
+                # If it's an integer
+                thuban_type = _raw_type_map.get(col_type)
+                if thuban_type is not None:
+                    col = (col_name, thuban_type)
+                elif row[1] == self.geometry_type:
+                    col = (col_name, "geometry")
+            if col is not None:
+                result.append(col)
+
+        return result
+
+    def cursor(self):
+        """Return a DB API 2.0 cursor for the database"""
+        return self.connection.cursor()
+
+
+
+class PostGISColumn:
+
+    """Column description for a PostGISTable
+
+    In addition to the normal column object attributes name, type and
+    index, PostGISColumn objects have a quoted_name attribute which
+    contains a quoted version of name for use in SQL statements. The
+    quoted_name attribute is mainly intended for internal use by the
+    PostGISTable class.
+    """
+
+    def __init__(self, name, type, index):
+        self.name = name
+        self.quoted_name = quote_identifier(name)
+        self.type = type
+        self.index = index
+
+
+class PostGISTable:
+
+    """A Table in a PostGIS database
+
+    A PostgreSQL table may contain columns with types not (yet)
+    supported by Thuban. Instances of this class ignore those columns
+    and pretend they don't exist, i.e. they won't show up in the column
+    descriptions returned by Columns() and other methods.
+    """
+
+    def __init__(self, db, tablename, id_column = None):
+        """Initialize the PostGISTable.
+
+        The db parameter should be an instance of PostGISConnection and
+        tablename the name of a table in the database represented by db.
+
+        The id_column parameter should be the name of a column in the
+        table that can be used to identify rows.  The column must have
+        the type integer and be unique and not null.
+
+        For backwards compatibility reasons, the id_column parameter is
+        optional.  If not given the table must have a column called
+        'gid' which is used as the id_column.  New code should always
+        provide this parameter.
+        """
+        self.db = db
+        self.tablename = tablename
+        # Tablename quoted for use in SQL statements.
+        self.quoted_tablename = quote_identifier(tablename)
+
+        if not id_column:
+            id_column = "gid"
+        self.id_column = id_column
+        # id column name quoted for use in SQL statements.
+        self.quoted_id_column = quote_identifier(id_column)
+
+        # Map column names and indices to column objects.
+        self.column_map = {}
+
+        self._fetch_table_information()
+
+    def _fetch_table_information(self):
+        """Internal: Update information about the table"""
+        self.columns = []
+        cursor = self.db.cursor()
+        cursor.execute("SELECT * FROM %s WHERE 0=1" % self.quoted_tablename)
+        description = cursor.description
+
+        for i in range(len(description)):
+            col = self._create_col_from_description(i, description[i])
+            if col is not None:
+                self.columns.append(col)
+
+        for col in self.columns:
+            self.column_map[col.name] = col
+            self.column_map[col.index] = col
+
+        # Build query string for ReadRowAsDict
+        self.query_stmt = ("SELECT %s from %s"
+                           % (", ".join([col.quoted_name
+                                         for col in self.columns]),
+                              self.quoted_tablename))
+
+    def _create_col_from_description(self, index, description):
+        """Return the column object for the column described by description
+
+        The parameter index is the index of the column.  The description
+        is a sequence taken from the cursor's description attribute for
+        the column.  That means description[0] is the name of the column
+        and description[1] the type.
+
+        Return None if the column can't be represented for some reason,
+        e.g. because its type is not yet supported or needs to be
+        treated in some special way.  Derived classes may extend this
+        method.
+        """
+        for pgtyp, tabletyp in type_map:
+            if pgtyp == description[1]:
+                return PostGISColumn(description[0], tabletyp,
+                                     len(self.columns))
+        return None
+
+    def DBConnection(self):
+        """Return the dbconnection used by the table"""
+        return self.db
+
+    def IDColumn(self):
+        """Return the column description object for the id column.
+
+        If the oid column was used as the id column, the return value is
+        not one of the regular column objects that would be returned by
+        e.g. the Column() method, but it still has meaningful name
+        attribute.
+        """
+        if self.id_column == "oid":
+            return PostGISColumn(self.id_column, table.FIELDTYPE_INT, None)
+        return self.column_map[self.id_column]
+
+    def TableName(self):
+        """Return the name of the table in the database"""
+        return self.tablename
+
+    def Title(self):
+        """Return the title of the table.
+
+        The title is currently fixed and equal to the tablename
+        """
+        return self.tablename
+
+    def Dependencies(self):
+        """Return an empty tuple because a PostGISTable depends on nothing else
+        """
+        return ()
+
+    def NumColumns(self):
+        return len(self.columns)
+
+    def Columns(self):
+        return self.columns
+
+    def Column(self, col):
+        return self.column_map[col]
+
+    def HasColumn(self, col):
+        return self.column_map.has_key(col)
+
+    def NumRows(self):
+        cursor = self.db.cursor()
+        cursor.execute("SELECT count(*) FROM %s" % self.quoted_tablename)
+        return cursor.fetchone()[0]
+
+    def RowIdToOrdinal(self, gid):
+        """Return the row ordinal given its id"""
+        cursor = self.db.cursor()
+        cursor.execute("SELECT count(*) FROM %s WHERE %s < %d;"
+                       % (self.quoted_tablename, self.quoted_id_column, gid))
+        return cursor.fetchone()[0]
+
+    def RowOrdinalToId(self, num):
+        """Return the rowid for given its ordinal"""
+        cursor = self.db.cursor()
+        cursor.execute("SELECT %s FROM %s LIMIT 1 OFFSET %d;"
+                       % (self.quoted_id_column, self.quoted_tablename, num))
+        return cursor.fetchone()[0]
+
+    def ReadRowAsDict(self, row, row_is_ordinal = 0):
+        cursor = self.db.cursor()
+        if row_is_ordinal:
+            stmt = self.query_stmt + " LIMIT 1 OFFSET %d" % row
+        else:
+            stmt = self.query_stmt + " WHERE %s = %d" % (self.quoted_id_column,
+                                                         row)
+        cursor.execute(stmt)
+        result = {}
+        for col, value in zip(self.columns, cursor.fetchone()):
+            result[col.name] = value
+        return result
+
+    def ReadValue(self, row, col, row_is_ordinal = 0):
+        cursor = self.db.cursor()
+        if row_is_ordinal:
+            stmt = ("SELECT %s FROM %s LIMIT 1 OFFSET %d" %
+                    (self.column_map[col].quoted_name, self.quoted_tablename,
+                     row))
+        else:
+            stmt = ("SELECT %s FROM %s WHERE %s = %d" %
+                    (self.column_map[col].quoted_name, self.quoted_tablename,
+                     self.quoted_id_column, row))
+        cursor.execute(stmt)
+        return cursor.fetchone()[0]
+
+    def ValueRange(self, col):
+        cursor = self.db.cursor()
+        name = self.column_map[col].quoted_name
+        cursor.execute("SELECT min(%s), max(%s) FROM %s" %
+                       (name, name, self.quoted_tablename))
+        return tuple(cursor.fetchone())
+
+    def UniqueValues(self, col):
+        cursor = self.db.cursor()
+        name = self.column_map[col].quoted_name
+        cursor.execute("SELECT %s FROM %s GROUP BY %s" %
+                       (name, self.quoted_tablename, name))
+        return [row[0] for row in cursor.fetchall()]
+
+    def SimpleQuery(self, left, comparison, right):
+        if comparison not in ("==", "!=", "<", "<=", ">=", ">"):
+            raise ValueError("Comparison operator %r not allowed" % comparison)
+
+        if comparison == "==":
+            comparison = "="
+
+        if isinstance(right, PostGISColumn):
+            right_template = right.quoted_name
+            params = ()
+        else:
+            right_template = "%s"
+            params = (right,)
+
+        query = "SELECT %s FROM %s WHERE %s %s %s ORDER BY %s;" \
+                % (self.quoted_id_column, self.quoted_tablename,
+                   left.quoted_name, comparison, right_template,
+                   self.quoted_id_column)
+
+        cursor = self.db.cursor()
+        cursor.execute(query, params)
+        result = []
+        while 1:
+            row = cursor.fetchone()
+            if row is None:
+                break
+            result.append(row[0])
+        return result
+
+
+class PostGISShape:
+
+    def __init__(self, shapeid, data):
+        self.shapeid = shapeid
+        self.data = data
+
+    def compute_bbox(self):
+        """
+        Return the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
+        """
+        xs = []
+        ys = []
+        for part in self.Points():
+            for x, y in part:
+                xs.append(x)
+                ys.append(y)
+        return (min(xs), min(ys), max(xs), max(ys))
+
+    def ShapeID(self):
+        return self.shapeid
+
+    def Points(self):
+        return wellknowntext.parse_wkt_thuban(self.data)
+
+    def RawData(self):
+        return self.data
+
+
+shapetype_map = {"POLYGON": SHAPETYPE_POLYGON,
+                 "MULTIPOLYGON": SHAPETYPE_POLYGON,
+                 "LINESTRING": SHAPETYPE_ARC,
+                 "MULTILINESTRING": SHAPETYPE_ARC,
+                 "POINT": SHAPETYPE_POINT}
+
+
+class PostGISShapeStore(PostGISTable):
+
+    """Shapestore interface to a table in a PostGIS database"""
+
+    def __init__(self, db, tablename, id_column = "gid",
+                 geometry_column = None):
+        """Initialize the PostGISShapeStore.
+
+        The db parameter should be an instance of PostGISConnection and
+        tablename the name of a table in the database represented by db.
+
+        The id_column parameter should be the name of a column in the
+        table that can be used to identify rows.  The column must have
+        the type integer and be unique and not null.
+
+        The geometry_column paramter, if given, should be the name of
+        the geometry column to use.  If the name given is not a geometry
+        column, raise a ValueError.
+
+        If no geometry_column is given, the table must have exactly one
+        geometry column.  If it has more than one and the
+        geometry_column is not given, a ValueError will be raised.
+        """
+        self.geometry_column = geometry_column
+        self.geometry_column_was_given = geometry_column is not None
+        PostGISTable.__init__(self, db, tablename, id_column)
+
+        # For convenience, we have a quoted version of the geometry
+        # column in self.quoted_geo_col
+        self.quoted_geo_col = quote_identifier(self.geometry_column)
+
+    def _fetch_table_information(self):
+        """Extend inherited method to retrieve the SRID and shape type"""
+        PostGISTable._fetch_table_information(self)
+
+        # First, try to get it from the geometry_columns table.
+        cursor = self.db.cursor()
+        cursor.execute("SELECT srid, type FROM geometry_columns"
+                       " WHERE f_table_name = %s AND f_geometry_column=%s",
+                       (self.tablename, self.geometry_column))
+        row = cursor.fetchone()
+        if row is not None:
+            self.srid = row[0]
+            self.shape_type = shapetype_map.get(row[1])
+            return
+
+        # The table is probably really a view and thus not in
+        # geometry_columns.  Use a different approach
+        cursor = self.db.cursor()
+        cursor.execute("SELECT DISTINCT SRID(%s) FROM %s;" %
+                       (quote_identifier(self.geometry_column),
+                        self.tablename))
+        row = cursor.fetchone()
+        if row is not None:
+            self.srid = row[0]
+            # Try to see whether there's another one
+            row = cursor.fetchone()
+            if row is not None:
+                # There are at least two different srids.  We don't
+                # support that
+                self.srid = None
+
+        cursor = self.db.cursor()
+        cursor.execute("SELECT DISTINCT GeometryType(%s) FROM %s;"
+                       % (quote_identifier(self.geometry_column),
+                          self.tablename))
+        row = cursor.fetchone()
+        if row is not None:
+            self.shape_type = shapetype_map.get(row[0])
+            # Try to see whether there's another one
+            row = cursor.fetchone()
+            if row is not None:
+                # There are at least two different srids.  We don't
+                # support that
+                self.shape_type = None
+
+    def _create_col_from_description(self, index, description):
+        """Extend the inherited method to find geometry columns
+
+        If the column indicated by the parameters is a geometry column,
+        record its name in self.geometry_column and a quoted version in
+        self.quoted_geo_col.  In any case return the return value of the
+        inherited method.
+        """
+        col = PostGISTable._create_col_from_description(self, index,
+                                                        description)
+        col_name, col_type = description[:2]
+        if self.geometry_column_was_given:
+            if (col_name == self.geometry_column
+                and col_type != self.db.geometry_type):
+                raise TypeError("Column %s in %s is not a geometry column"
+                                % (self.geometry_column, self.tablename))
+        else:
+            if col is None:
+                if description[1] == self.db.geometry_type:
+                    # The column is a geometry column.  If the name of
+                    # the geometry column was not given to the
+                    # constructor, and we encounter two geometry
+                    # columns, raise a value error
+                    if self.geometry_column is None:
+                        self.geometry_column = description[0]
+                    else:
+                        raise TypeError("Table %s has two geometry columns"
+                                        " and no column name was given"
+                                        % (self.tablename,))
+        return col
+
+    def Table(self):
+        """Return self since a PostGISShapeStore is its own table."""
+        return self
+
+    def OrigShapeStore(self):
+        """Return None since the PostGISShapeStore is not derived from another
+        """
+        return None
+
+    def GeometryColumn(self):
+        """Return the column description object for the geometry column
+
+        There's currently no FIELDTYPE constant for this column, so the
+        return value is not a regular column object that could also be
+        returned from e.g. the Column() method.  Only the name attribute
+        of the return value is meaningful at the moment.
+        """
+        return PostGISColumn(self.geometry_column, None, None)
+
+    def ShapeType(self):
+        """Return the type of the shapes in the shapestore."""
+        return self.shape_type
+
+    def RawShapeFormat(self):
+        """Return the raw data format of the shape data.
+
+        For the PostGISShapeStore this is RAW_WKT.
+        """
+        return RAW_WKT
+
+    def NumShapes(self):
+        # The number of shapes is the same as the number of rows,
+        # assuming that the geometry can't be NULL.
+        return self.NumRows()
+
+    def BoundingBox(self):
+        """Return the bounding box of all shapes in the postgis table"""
+        minx = miny = maxx = maxy = None
+        x=[]
+        y=[]
+        cursor = self.db.cursor()
+        try:
+            # Using the extent function is postgis specific. An OGC
+            # Simple Features compliant solution would be to use a query
+            # like "SELECT AsText(Envelope(the_geom)) FROM mytable;" and
+            # calculate the bounding box by hand from that
+            cursor.execute("SELECT extent(%s) FROM %s;"
+                           % (self.quoted_geo_col, self.quoted_tablename))
+            result = cursor.fetchone()
+            if result[0]:
+                (minx, miny), (maxx, maxy) \
+                      = wellknowntext.parse_wkt_thuban(result[0])[0]
+                return (minx, miny, maxx, maxy)
+        finally:
+            cursor.close()
+
+    def Shape(self, shapeid):
+        cursor = self.db.cursor()
+        cursor.execute("SELECT AsText(%s) FROM %s WHERE %s=%d"
+                       % (self.quoted_geo_col, self.quoted_tablename,
+                          self.quoted_id_column, shapeid))
+        wkt = cursor.fetchone()[0]
+        cursor.close()
+        return PostGISShape(shapeid, wkt)
+
+    def AllShapes(self):
+        cursor = self.db.cursor()
+        cursor.execute("SELECT %s, AsText(%s) FROM %s ORDER BY %s"
+                       % (self.quoted_id_column, self.quoted_geo_col,
+                          self.quoted_tablename, self.quoted_id_column))
+        while 1:
+            result = cursor.fetchone()
+            if result is None:
+                return
+            yield PostGISShape(result[0], result[1])
+
+
+    def ShapesInRegion(self, bbox):
+        """Generate all shapes overlapping the region given by bbox."""
+        # IMPORTANT:This will work for PostGIS < 0.8
+        left, bottom, right, top = bbox
+        geom = (("POLYGON((" + ", ".join(["%f %f"] * 5) + "))")
+                % (left, bottom, left, top, right, top, right, bottom,
+                   left, bottom))
+        cursor = self.db.cursor()
+        cursor.execute("SELECT %(gid)s, AsText(%(geom)s) FROM %(table)s"
+                     " WHERE %(geom)s && GeometryFromText('%(box)s', %(srid)d)"
+                       " ORDER BY %(gid)s"
+                       % {"table": self.quoted_tablename,
+                          "geom": self.quoted_geo_col,
+                          "gid": self.quoted_id_column,
+                          "box": geom,
+                          "srid": self.srid})
+        while 1:
+            result = cursor.fetchone()
+            if result is None:
+                return
+            yield PostGISShape(result[0], result[1])

Added: packages/thuban/branches/upstream/current/Thuban/Model/proj.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/proj.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/proj.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,218 @@
+# Copyright (c) 2001, 2003, 2006 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Bernhard Reiter <bernhard at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+__version__ = "$Revision: 2708 $"
+
+from types import StringTypes
+import locale
+
+from Thuban import _
+from Thuban.Lib.connector import Publisher
+
+import Projection
+BaseProjection = Projection.Projection
+del Projection
+
+from messages import PROJECTION_ADDED, PROJECTION_REPLACED, PROJECTION_REMOVED
+
+PROJ_UNITS_METERS  = 1
+PROJ_UNITS_DEGREES = 2
+
+def _do_we_have_to_work_around_broken_proj():
+    """ If we have a problematic locale, check if proj results are good. """
+    if locale.localeconv()['decimal_point'] != '.':
+        params = ["proj=latlong", "to_meter=0.01745", "ellps=clrk66"]
+        proj = BaseProjection(params)
+        result1 = proj.Forward(1,1)
+
+        savedlocale = locale.getlocale(locale.LC_NUMERIC)
+        locale.setlocale(locale.LC_NUMERIC, "C")
+
+        proj = BaseProjection(params)
+        result2 = proj.Forward(1,1)
+
+        try:
+            locale.setlocale(locale.LC_NUMERIC, savedlocale)
+        except:
+            # python under some circumstances (observed 2.3.5-2 Debian Sarge)
+            # does not accept savedlocale directly 
+            # deviating from the documentation
+            locale.setlocale(locale.LC_NUMERIC, savedlocale[0])
+        if result1 != result2:
+            return True
+    return False
+
+class Projection(BaseProjection):
+    """A proj4 projection object that remembers the parameters.
+
+    The proj library is not robust against decimal_point != '.' locales.
+    Since python 2.4 calls C extensions with the set locale, it can create
+    a problem.  It seems that calling
+        self.assuregoodlocale()
+        self.assureinitlocale()
+    before BaseProjection.__init__() is enough to work around this.
+
+    We assuming that the locale stays the same after a projection
+    has been initialised 
+    and thus we can return to it in self.assureinitlocale().
+    """
+
+    def __init__(self, params, name = None, epsg = None):
+        """Initialize the Projection
+
+        Parameters:
+
+        params -- a list of 'parameter=value' strings
+
+        name -- (optional) The name of the projection. If None or omitted
+                it defaults to 'Unknown' in the local language.
+
+        epsg -- (optional) The EPSG code as a string.
+        """
+        self.initlocale = locale.getlocale(locale.LC_NUMERIC)
+        self.work_around_broken_proj = _do_we_have_to_work_around_broken_proj()
+
+        self.assuregoodlocale()
+        BaseProjection.__init__(self, params)
+        self.assureinitlocale()
+
+        if name is None:
+            self.name = _("Unknown")
+        elif isinstance(name, StringTypes):
+            self.name = name
+
+        self.epsg = epsg
+        self.params = params
+
+    def assuregoodlocale(self):
+        if self.work_around_broken_proj:
+            locale.setlocale(locale.LC_NUMERIC, "C")
+
+    def assureinitlocale(self):
+        if self.work_around_broken_proj:
+            locale.setlocale(locale.LC_NUMERIC, self.initlocale)
+
+    def _transform_bbox(self, trafo, bbox):
+        # This is not really the correct way to determine the bbox of a
+        # projected bbox, but for now it works well enough
+        llx, lly, urx, ury = bbox
+        xs = []; ys = []
+        for x, y in ((llx, lly), (llx, ury), (urx, lly), (urx, ury)):
+            x, y = trafo(x, y)
+            xs.append(x); ys.append(y)
+        return min(xs), min(ys), max(xs), max(ys)
+
+    def ForwardBBox(self, bbox):
+        """Return the bounding box of the corners of the bounding box bbox
+        """
+        return self._transform_bbox(self.Forward, bbox)
+
+    def InverseBBox(self, bbox):
+        return self._transform_bbox(self.Inverse, bbox)
+
+    def GetName(self):
+        """Return the name of the projection."""
+        return self.name
+
+    def Label(self):
+        if self.epsg:
+            return "EPSG % 5s %s" % (self.epsg, self.name)
+        return self.name
+
+    def EPSGCode(self):
+        """Return the EPSG code as a string or None if there is none"""
+        return self.epsg
+
+    def GetParameter(self, param):
+        """Return the projection value for the given parameter.
+
+        If 'param' exists as a valid parameter return the associated
+        value as a string. If the parameter does not have a value (like
+        e.g. the 'south' parameter for utm) then the value is the
+        parameter name itself.
+
+        If the parameter doesn't exist return an empty string.
+        """
+
+        for pair in self.params:
+            if "=" in pair:
+                p, v = pair.split("=")
+            else:
+                p = v = pair
+            if p == param:
+                return v
+
+        return ""
+
+    def GetAllParameters(self):
+        """Return list of 'parameter=value' strings"""
+        return self.params
+
+    def GetProjectedUnits(self):
+        if self.GetParameter("proj") in [ 'latlong', 'longlat' ]:
+            return PROJ_UNITS_DEGREES
+        else:
+            return PROJ_UNITS_METERS
+
+    def __repr__(self):
+        return self.name + ": " + repr(self.params)
+
+
+class ProjFile(Publisher):
+
+    def __init__(self, filename):
+        """Intialize the ProjFile.
+
+        filename -- name of the file that this ProjFile represents.
+        """
+
+        self.__projs = []
+
+        self.SetFilename(filename)
+
+    def Add(self, proj):
+        """Add the projection to the end of the file."""
+        self.__projs.append(proj)
+        self.issue(PROJECTION_ADDED, proj)
+
+    def Remove(self, proj):
+        """Remove the object proj from the projection file.
+
+        Raises a ValueError is proj is not found.
+        """
+        self.__projs.remove(proj)
+        self.issue(PROJECTION_REMOVED, proj)
+
+    def Replace(self, oldproj, newproj):
+        """Replace the object 'oldproj' with 'newproj'.
+
+        Raises ValueError if oldproj is not in the file.
+        """
+        self.__projs[self.__projs.index(oldproj)] = newproj
+        self.issue(PROJECTION_REPLACED, oldproj, newproj)
+
+    def GetFilename(self):
+        """Return the filename where the ProjFile was read or will be
+        written to.
+        """
+
+        return self.__filename
+
+    def SetFilename(self, filename):
+        """Set the filename where the ProjFile will be written to."""
+        self.__filename = filename
+
+    def GetProjections(self):
+        """Return a list of the projections in the order they were read
+        from the file or will be written.
+
+        This is not a deep copy list, so any modifications made to the
+        Projection objects will be written to the file.
+        """
+
+        return self.__projs
+

Added: packages/thuban/branches/upstream/current/Thuban/Model/range.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/range.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/range.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,146 @@
+# Copyright (C) 2002, 2003 by Intevation GmbH
+# Authors:
+# Thomas Koester <tkoester at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""
+Range class for Scientific Parameter
+"""
+
+__version__ = "$Revision: 1480 $"
+# $Source$
+# $Id: range.py 1480 2003-07-24 17:52:48Z bh $
+
+import re
+import types
+
+_inf = float('1e1000')   # FIXME: hack for infinite
+
+class Range:
+
+    number_re = '(?P<%s>-?(\d*\.?\d*([eE][\-+]?\d+)?|oo))'
+    brace_re = '(?P<%s>[][])'
+    range_re = '^' + brace_re % 'left' + number_re % 'begin' + \
+               ';' + number_re % 'end' + brace_re % 'right' + '$'
+    parse_range = re.compile(range_re)
+
+    def __init__(self, range=None):
+        self._SetRange(range)
+
+    def _SetRange(self, range):
+        if isinstance(range, Range):
+            self._SetRange(range.GetRange())
+        elif range in [None, '']:
+            self._SetRange(']-oo;oo[')
+        elif type(range) == types.TupleType:
+            if (len(range) == 4 and range[0] in ['[', ']']
+                and range[3] in ['[', ']']):
+                self._left = range[0]
+                self._begin = self.float(range[1])
+                self._end = self.float(range[2])
+                self._right = range[3]
+                if (self._begin > self._end or
+                    (self._begin == self._end and
+                     (self._left != '[' or self._right != ']'))):
+                    raise ValueError("illegal range: %s" % (range,))
+            else:
+                raise ValueError("can't parse range: %r" % (range,))
+        else:
+            self._range = range
+            match = self.parse_range.match(self._range)
+            if match:
+                self._SetRange((match.group('left'),
+                              match.group('begin'),
+                              match.group('end'),
+                              match.group('right')))
+            else:
+                raise ValueError("can't parse range: %s" % (range,))
+
+    def GetRange(self):
+        """return internal representation of range
+
+        4-tuple ('[' or ']', begin(float), end(float), '[' or ']')
+
+        """
+        return (self._left, self._begin, self._end, self._right)
+
+    def float(self, value):
+        """convert string or number to float"""
+        if value == 'oo':
+            return _inf
+        elif value == '-oo':
+            return -_inf
+        else:
+            return float(value)
+
+    def _float2string(self, value):
+        """convert float value to string
+
+        (minus) infinity will be converted to (-)oo,
+        scientific notation will be used if necessary.
+
+        """
+        if value == _inf:
+            return 'oo'
+        elif value == -_inf:
+            return '-oo'
+        else:
+            return "%g" % (value,)
+
+    def string(self, range):
+        """convert internal representation to string"""
+        left, begin, end, right = range
+        return "%s%s;%s%s" % (left, self._float2string(begin),
+                              self._float2string(end), right)
+
+    def __contains__(self, value):
+        if self._left == ']':
+            contains = value > self._begin
+        else:
+            contains = value >= self._begin
+        if self._right == '[':
+            contains = contains and (value < self._end)
+        else:
+            contains = contains and (value <= self._end)
+        return contains
+
+    def __eq__(self, other):
+        return (self.GetRange() == other.GetRange())
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.string(self.GetRange())
+
+
+def _test():
+    range1 = Range(']0;99]')
+    print 'range1 =', range1, range1.GetRange()
+    for i in [-0.1, 0, 0.1, 9.9, 99, 99.9]:
+        print '%4.1f in range1 =' % i, i in range1
+    range2 = Range(']-oo;10[')
+    print 'range2 =', range2, range2.GetRange()
+    for i in [-0.1, 0, 0.1, 9.9, 10, 10.1]:
+        print '%4.1f not in range2 =' % i, i not in range2
+    range3 = Range(']1e-1;1E2]')
+    print 'range3 =', range3, range3.GetRange()
+    for i in [0, 0.1, 0.11, 10, 100, 101]:
+        print '%4.1f not in range3 =' % i, i not in range3
+    print 'range3 != range2 =', range3 != range2
+    print 'range3 != Range("]1e-1;1E2]") =', range3 != Range("]1e-1;1E2]")
+
+    range4 = Range('')
+    print 'range4 =', range4, range4.GetRange()
+
+    range5 = Range(']0;99E+00]')
+    print 'range5 =', range5, range5.GetRange()
+    range6 = Range(']0;99E+01]')
+    print 'range6 =', range6, range6.GetRange()
+    range7 = Range(']0;99E-01]')
+    print 'range7 =', range7, range7.GetRange()
+
+if __name__ == "__main__":
+    _test()

Added: packages/thuban/branches/upstream/current/Thuban/Model/resource.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/resource.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/resource.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,235 @@
+# Copyright (c) 2003 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Handle resources loaded from files such as projections"""
+
+__version__ = "$Revision: 1964 $"
+# $Source$
+# $Id: resource.py 1964 2003-11-19 19:48:47Z bh $
+
+
+import os
+import os.path
+import weakref
+import traceback
+
+import Thuban
+from Thuban import _
+
+from Thuban.Lib.fileutil import get_application_dir
+
+from Thuban.Model.xmlreader import XMLReader
+from Thuban.Model.xmlwriter import XMLWriter
+from Thuban.Model.proj import Projection, ProjFile
+from xml.sax import SAXParseException
+
+projdir = \
+        os.path.join(Thuban.__path__[0], os.pardir, "Resources", "Projections")
+
+
+PROJ_EXT = ".proj"
+
+# Determine the status of GDAL support. If GDAL is supported
+# gdal_support_status will be set to the empty string, otherwise to a
+# string with information why it isn't supported
+#
+# GDAL is supported if we can import both the thuban specific gdalwarp
+# module and the GDAL python bindings.
+for _module in ("gdalwarp", "gdal"):
+    try:
+        __import__(_module)
+    except ImportError, val:
+        gdal_support_status = (_("No GDAL support because module '%s'"
+                                 " cannot be imported. Python exception: '%s'")
+                               % (_module, str(val)))
+        break
+else:
+    gdal_support_status = ""
+
+def has_gdal_support():
+    return gdal_support_status == ""
+
+
+projfile_cache = weakref.WeakValueDictionary()
+
+def clear_proj_file_cache():
+    """Clear the cache of ProjFile objects maintained by read_proj_file.
+
+    This function is probably only useful for the test suite.
+    """
+    projfile_cache.clear()
+
+def read_proj_file(filename):
+    """Read a .proj file and return a ProjFile object and warnings
+
+    The return value is a tuple with the ProjFile object and a list of
+    strings with warnings messages that might have been generated by the
+    proj file parser.
+
+    The objects returned cached so that reading the same file
+    (identified by its absolute name) several times yields the same
+    ProjFile object. The cache uses weak references so the objects will
+    be removed from the cache once the last reference an object in the
+    cache is removed.
+
+    Raises IOError if the file cannot be opened, OSError if the file
+    cannot be read and SAXParseException if the file is not valid XML.
+    """
+    filename = os.path.abspath(filename)
+    if filename in projfile_cache:
+        return projfile_cache[filename], []
+    else:
+        handler = ProjFileReader()
+        handler.read(filename)
+        proj_file = handler.GetProjFile()
+        projfile_cache[filename] = proj_file
+        return proj_file, handler.GetWarnings()
+
+def write_proj_file(pf):
+    """Write a single .proj file
+
+    Raises IOError if the file cannot be written.
+    """
+
+    saver = ProjFileSaver(pf)
+    saver.write(pf.GetFilename())
+
+#
+# Constants for the get_system_proj_file function
+#
+
+# The default projection file with a few predefined projections
+DEFAULT_PROJ_FILE = "defaults.proj"
+
+# The epsg projections.
+EPSG_PROJ_FILE = "epsg.proj"
+
+# Deprecated EPSG projections.
+EPSG_DEPRECATED_PROJ_FILE = "epsg-deprecated.proj"
+
+def get_system_proj_file(filename):
+    """Return the projections from the indicated file and a list with warnings
+
+    The filename argument should be the name of a file in the directory
+    with Thuban's default projection files (Resources/Projections/). If
+    possible callers should not use hardwired string literal for the
+    name to avoid unnecessary duplication. Instead they should use one
+    of the predefined constants, currently DEFAULT_PROJ_FILE,
+    EPSG_PROJ_FILE or EPSG_DEPRECATED_PROJ_FILE.
+
+    The return value is a tuple with the projections in a ProjFile
+    object and a list of strings with warning messages. The warnings
+    list is usually empty but may contain messages about ignored errors.
+
+    If the file could could not be opened return an empty projection
+    file object set to store data in the indicated default file.
+    """
+    fullname = os.path.join(projdir, filename)
+    try:
+        return read_proj_file(fullname)
+    except (OSError, IOError, SAXParseException), val:
+        msg = _('Could not read "%s": %s') % (fullname, str(val))
+        return ProjFile(fullname), [msg]
+
+def get_user_proj_file():
+    """Return the user's projections and a list with warnings
+
+    The projections read from the user's thuban projection file (usually
+    in ~/.thuban/user.proj). The return value is a tuple with the
+    projections in a ProjFile object and a list of strings with warning
+    messages. The warnings list is usually empty but may contain
+    messages about ignored errors.
+
+    If the file could could not be opened return an empty projection
+    file object set to store data in the default file.
+    """
+    usrdir  = get_application_dir()
+    filename = os.path.join(usrdir, "user.proj")
+    try:
+        return read_proj_file(filename)
+    except (OSError, IOError, SAXParseException), val:
+        msg = _('Could not read "%s": %s') % (filename, str(val))
+        return ProjFile(filename), [msg]
+
+
+class ProjFileReader(XMLReader):
+
+    def __init__(self):
+        XMLReader.__init__(self)
+        self.projfile = ProjFile("")
+        self.warnings = []
+
+        XMLReader.AddDispatchers(self,
+            {'projection': ("start_projection", "end_projection"),
+             'parameter':  ("start_parameter", None)})
+
+    def read(self, file_or_filename):
+        XMLReader.read(self, file_or_filename)
+
+        self.projfile.SetFilename(XMLReader.GetFilename(self))
+
+    def start_projection(self, name, qname, attrs):
+        self.params = []
+        name = self.encode(attrs.get((None, 'name')))
+        if name is None:
+            name = _("Unknown")
+        self.name = name
+        self.epsg = self.encode(attrs.get((None, 'epsg')))
+
+    def end_projection(self, name, qname):
+        try:
+            proj = Projection(self.params, self.name, epsg = self.epsg)
+        except IOError, val:
+            self.warnings.append(_('Error in projection "%s": %s')
+                                 % (self.name, str(val)))
+        else:
+            self.projfile.Add(proj)
+
+    def start_parameter(self, name, qname, attrs):
+        s = attrs.get((None, 'value'))
+        s = str(s) # we can't handle unicode in proj
+        self.params.append(s)
+
+    def GetProjFile(self):
+        return self.projfile
+
+    def GetWarnings(self):
+        """Return the list of warning messages that may have been produced"""
+        return self.warnings
+
+
+class ProjFileSaver(XMLWriter):
+
+    def __init__(self, pf):
+        XMLWriter.__init__(self)
+        self.__pf = pf
+
+    def write(self, file_or_filename):
+        XMLWriter.write(self, file_or_filename)
+
+        self.write_header("projectionlist", "projfile.dtd")
+        self.write_projfile(self.__pf)
+        self.close()
+
+    def write_projfile(self, pf):
+
+        self.open_element("projectionlist")
+
+        for p in pf.GetProjections():
+            attrs = {"name": p.GetName()}
+            if p.EPSGCode():
+                attrs["epsg"] = p.EPSGCode()
+            self.open_element("projection", attrs)
+
+            for param in p.GetAllParameters():
+                self.write_element("parameter", {"value": param})
+
+            self.close_element("projection")
+
+        self.close_element("projectionlist")
+
+

Added: packages/thuban/branches/upstream/current/Thuban/Model/save.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/save.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/save.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,405 @@
+# Copyright (c) 2001-2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2004-2005)
+# Bernhard Herzog <bh at intevation.de> (2001-2004)
+# Jonathan Coles <jonathan at intevation.de> (2003)
+# Frank Koormann <frank at intevation.de> (2003)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Functions to save a session to a file
+"""
+
+__version__ = "$Revision: 2688 $"
+# $Source$
+# $Id: save.py 2688 2006-06-30 12:27:20Z frank $
+
+import os
+
+import Thuban.Lib.fileutil
+
+from Thuban.Model.layer import Layer, RasterLayer
+
+from Thuban.Model.classification import \
+    ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, \
+    ClassGroupPattern, ClassGroupMap
+from Thuban.Model.transientdb import AutoTransientTable, TransientJoinedTable
+from Thuban.Model.table import DBFTable, FIELDTYPE_STRING
+from Thuban.Model.data import DerivedShapeStore, FileShapeStore, \
+                              SHAPETYPE_POINT
+
+from Thuban.Model.xmlwriter import XMLWriter
+from postgisdb import PostGISConnection, PostGISShapeStore
+
+def relative_filename(dir, filename):
+    """Return a filename relative to dir for the absolute file name absname.
+
+    This is almost the same as the function in fileutil, except that dir
+    can be an empty string in which case filename will be returned
+    unchanged.
+    """
+    if dir:
+        return Thuban.Lib.fileutil.relative_filename(dir, filename)
+    else:
+        return filename
+
+
+def unify_filename(filename):
+    """Return a 'unified' version of filename
+
+    The .thuban files should be as platform independent as possible.
+    Since they must contain filenames the filenames have to unified. We
+    unify on unix-like filenames for now, which means we do nothing on a
+    posix system and simply replace backslashes with slashes on windows
+    """
+    if os.name == "posix":
+        return filename
+    elif os.name == "nt":
+        return "/".join(filename.split("\\"))
+    else:
+        raise RuntimeError("Unsupported platform for unify_filename: %s"
+                           % os.name)
+
+def sort_data_stores(stores):
+    """Return a topologically sorted version of the sequence of data containers
+
+    The list is sorted so that data containers that depend on other data
+    containers have higher indexes than the containers they depend on.
+    """
+    if not stores:
+        return []
+    processed = {}
+    result = []
+    todo = stores[:]
+    while todo:
+        # It doesn't really matter which if the items of todo is
+        # processed next, but if we take the first one, the order is
+        # preserved to some degree which makes writing some of the test
+        # cases easier.
+        container = todo.pop(0)
+        if id(container) in processed:
+            continue
+        deps = [dep for dep in container.Dependencies()
+                    if id(dep) not in processed]
+        if deps:
+            todo.append(container)
+            todo.extend(deps)
+        else:
+            result.append(container)
+            processed[id(container)] = 1
+    return result
+
+def bool2str(b):
+    if b: return "true"
+    else: return "false"
+
+class SessionSaver(XMLWriter):
+
+    """Class to serialize a session into an XML file.
+
+    Applications built on top of Thuban may derive from this class and
+    override or extend the methods to save additional information. This
+    additional information should take the form of additional attributes
+    or elements whose names are prefixed with a namespace. To define a
+    namespace derived classes should extend the write_session method to
+    pass the namespaces to the default implementation.
+    """
+
+
+    def __init__(self, session):
+        XMLWriter.__init__(self)
+        self.session = session
+        # Map object ids to the ids used in the thuban files
+        self.idmap = {}
+
+    def get_id(self, obj):
+        """Return the id used in the thuban file for the object obj"""
+        return self.idmap.get(id(obj))
+
+    def define_id(self, obj, value = None):
+        if value is None:
+            value = "D" + str(id(obj))
+        self.idmap[id(obj)] = value
+        return value
+
+    def has_id(self, obj):
+        return self.idmap.has_key(id(obj))
+
+    def prepare_filename(self, filename):
+        """Return the string to use when writing filename to the thuban file
+
+        The returned string is a unified version (only slashes as
+        directory separators, see unify_filename) of filename expressed
+        relative to the directory the .thuban file is written to.
+        """
+        return unify_filename(relative_filename(self.dir, filename))
+
+    def write(self, file_or_filename):
+        XMLWriter.write(self, file_or_filename)
+
+        self.write_header("session", "thuban-1.1.dtd")
+        self.write_session(self.session)
+        self.close()
+
+    def write_session(self, session, attrs = None, namespaces = ()):
+        """Write the session and its contents
+
+        By default, write a session element with the title attribute and
+        call write_map for each map contained in the session.
+
+        The optional argument attrs is for additional attributes and, if
+        given, should be a mapping from attribute names to attribute
+        values. The values should not be XML-escaped yet.
+
+        The optional argument namespaces, if given, should be a sequence
+        of (name, URI) pairs. The namespaces are written as namespace
+        attributes into the session element. This is mainly useful for
+        derived classes that need to store additional information in a
+        thuban session file.
+        """
+        if attrs is None:
+            attrs = {}
+        attrs["title"] = session.title
+        for name, uri in namespaces:
+            attrs["xmlns:" + name] = uri
+        # default name space
+        attrs["xmlns"] = \
+               "http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        self.open_element("session", attrs)
+        self.write_db_connections(session)
+        self.write_data_containers(session)
+        for map in session.Maps():
+            self.write_map(map)
+        self.close_element("session")
+
+    def write_db_connections(self, session):
+        for conn in session.DBConnections():
+            if isinstance(conn, PostGISConnection):
+                self.write_element("dbconnection",
+                                   {"id": self.define_id(conn),
+                                    "dbtype": "postgis",
+                                    "host": conn.host,
+                                    "port": conn.port,
+                                    "user": conn.user,
+                                    "dbname": conn.dbname})
+            else:
+                raise ValueError("Can't handle db connection %r" % conn)
+
+    def write_data_containers(self, session):
+        containers = sort_data_stores(session.DataContainers())
+        for container in containers:
+            if isinstance(container, AutoTransientTable):
+                # AutoTransientTable instances are invisible in the
+                # thuban files. They're only used internally. To make
+                # sure that containers depending on AutoTransientTable
+                # instances refer to the right real containers we give
+                # the AutoTransientTable instances the same id as the
+                # source they depend on.
+                self.define_id(container,
+                               self.get_id(container.Dependencies()[0]))
+                continue
+
+            idvalue = self.define_id(container)
+            if isinstance(container, FileShapeStore):
+                self.define_id(container.Table(), idvalue)
+                filename = self.prepare_filename(container.FileName())
+                self.write_element("fileshapesource",
+                                   {"id": idvalue, "filename": filename,
+                                    "filetype": container.FileType()})
+            elif isinstance(container, DerivedShapeStore):
+                shapesource, table = container.Dependencies()
+                self.write_element("derivedshapesource",
+                                   {"id": idvalue,
+                                    "shapesource": self.get_id(shapesource),
+                                    "table": self.get_id(table)})
+            elif isinstance(container, PostGISShapeStore):
+                conn = container.DBConnection()
+                self.write_element("dbshapesource",
+                                   {"id": idvalue,
+                                    "dbconn": self.get_id(conn),
+                                    "tablename": container.TableName(),
+                                    "id_column": container.IDColumn().name,
+                                    "geometry_column":
+                                      container.GeometryColumn().name,
+                                    })
+            elif isinstance(container, DBFTable):
+                filename = self.prepare_filename(container.FileName())
+                self.write_element("filetable",
+                                   {"id": idvalue,
+                                    "title": container.Title(),
+                                    "filename": filename,
+                                    "filetype": "DBF"})
+            elif isinstance(container, TransientJoinedTable):
+                left, right = container.Dependencies()
+                left_field = container.left_field
+                right_field = container.right_field
+                self.write_element("jointable",
+                                   {"id": idvalue,
+                                    "title": container.Title(),
+                                    "right": self.get_id(right),
+                                    "rightcolumn": right_field,
+                                    "left": self.get_id(left),
+                                    "leftcolumn": left_field,
+                                    "jointype": container.JoinType()})
+            else:
+                raise ValueError("Can't handle container %r" % container)
+
+
+    def write_map(self, map):
+        """Write the map and its contents.
+
+        By default, write a map element element with the title
+        attribute, call write_projection to write the projection
+        element, call write_layer for each layer contained in the map
+        and finally call write_label_layer to write the label layer.
+        """
+        self.open_element('map title="%s"' % self.encode(map.title))
+        self.write_projection(map.projection)
+        for layer in map.Layers():
+            self.write_layer(layer)
+        self.write_label_layer(map.LabelLayer())
+        self.close_element('map')
+
+    def write_projection(self, projection):
+        """Write the projection.
+        """
+        if projection and len(projection.params) > 0:
+            attrs = {"name": projection.GetName()}
+            epsg = projection.EPSGCode()
+            if epsg is not None:
+                attrs["epsg"] = epsg
+            self.open_element("projection", attrs)
+            for param in projection.params:
+                self.write_element('parameter value="%s"' % 
+                                   self.encode(param))
+            self.close_element("projection")
+
+    def write_layer(self, layer, attrs = None):
+        """Write the layer.
+
+        The optional argument attrs is for additional attributes and, if
+        given, should be a mapping from attribute names to attribute
+        values. The values should not be XML-escaped yet.
+        """
+
+        if attrs is None:
+            attrs = {}
+
+        attrs["title"]   = layer.title
+        attrs["visible"] = bool2str(layer.Visible())
+
+        if isinstance(layer, Layer):
+            attrs["shapestore"]   = self.get_id(layer.ShapeStore())
+            self.open_element("layer", attrs)
+            self.write_projection(layer.GetProjection())
+            self.write_classification(layer)
+            self.close_element("layer")
+        elif isinstance(layer, RasterLayer):
+            attrs["filename"] = self.prepare_filename(layer.filename)
+
+            masknames = ["none", "bit", "alpha"]
+
+            if layer.MaskType() != layer.MASK_BIT:
+                attrs["masktype"] = masknames[layer.MaskType()]
+
+            if layer.Opacity() != 1:
+                attrs["opacity"] = str(layer.Opacity())
+
+            self.open_element("rasterlayer", attrs)
+            self.write_projection(layer.GetProjection())
+            self.close_element("rasterlayer")
+
+    def write_classification(self, layer, attrs = None):
+        """Write Classification information."""
+
+        if attrs is None:
+            attrs = {}
+
+        lc = layer.GetClassification()
+
+        field = layer.GetClassificationColumn()
+
+        if field is not None:
+            attrs["field"] = field
+            attrs["field_type"] = str(layer.GetFieldType(field))
+
+        self.open_element("classification", attrs)
+
+        for g in lc:
+            if isinstance(g, ClassGroupDefault):
+                open_el  = 'clnull label="%s"' % self.encode(g.GetLabel())
+                close_el = 'clnull'
+            elif isinstance(g, ClassGroupSingleton):
+                if layer.GetFieldType(field) == FIELDTYPE_STRING:
+                    value = self.encode(g.GetValue())
+                else:
+                    value = str(g.GetValue())
+                open_el  = 'clpoint label="%s" value="%s"' \
+                           % (self.encode(g.GetLabel()), value)
+                close_el = 'clpoint'
+            elif isinstance(g, ClassGroupRange):
+                open_el  = 'clrange label="%s" range="%s"' \
+                          % (self.encode(g.GetLabel()), str(g.GetRange()))
+                close_el = 'clrange'
+            elif isinstance(g, ClassGroupPattern):
+                open_el  = 'clpattern label="%s" pattern="%s"' \
+                          % (self.encode(g.GetLabel()), str(g.GetPattern()))
+                close_el = 'clpattern'
+
+            else:
+                assert False, _("Unsupported group type in classification")
+                continue
+
+            data = g.GetProperties()
+            dict = {'stroke'      : data.GetLineColor().hex(),
+                    'stroke_width': str(data.GetLineWidth()),
+                    'fill'        : data.GetFill().hex()}
+
+            # only for point layers write the size attribute
+            if layer.ShapeType() == SHAPETYPE_POINT:
+                dict['size'] =  str(data.GetSize())
+
+            self.open_element(open_el)
+            self.write_element("cldata", dict)
+            self.close_element(close_el)
+
+        self.close_element("classification")
+
+    def write_label_layer(self, layer):
+        """Write the label layer.
+        """
+        labels = layer.Labels()
+        if labels:
+            self.open_element('labellayer')
+            for label in labels:
+                self.write_element(('label x="%g" y="%g" text="%s"'
+                                    ' halign="%s" valign="%s"')
+                                % (label.x, label.y, 
+                                   self.encode(label.text), 
+                                   label.halign,
+                                   label.valign))
+            self.close_element('labellayer')
+
+
+
+def save_session(session, file, saver_class = None):
+    """Save the session session to a file.
+
+    The file argument may either be a filename or an open file object.
+
+    The optional argument saver_class is the class to use to serialize
+    the session. By default or if it's None, the saver class will be
+    SessionSaver.
+
+    If writing the session is successful call the session's
+    UnsetModified method
+    """
+    if saver_class is None:
+        saver_class = SessionSaver
+    saver = saver_class(session)
+    saver.write(file)
+
+    # after a successful save consider the session unmodified.
+    session.UnsetModified()

Added: packages/thuban/branches/upstream/current/Thuban/Model/scalebar.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/scalebar.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/scalebar.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,58 @@
+# Copyright (c) 2001, 2002 by Intevation GmbH
+# Authors:
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 913 $"
+
+from Thuban import _
+
+def deriveInterval(width, scale):
+    """Calculate scalebar interval and unit which fits width for scale."""
+    try:
+        interval = width / scale
+    except ZeroDivisionError:
+        return -1, ''
+
+    if interval / 1000 > 1:
+        interval = long(interval / 1000)
+        unit = 'km'
+    else: 
+        interval = long(interval)
+        unit = 'm'
+
+    return interval, unit
+
+def roundInterval(d):
+    """Round float."""
+    if d<.001: 
+        interval = long(d*10000)/10000.0
+        return interval, "%.4f" % interval
+    if d<.01:
+        interval = long(d*1000)/1000.0
+        return interval, "%.3f" % interval
+    if d<.1:
+        interval = long(d*100)/100.0
+        return interval, "%.2f" % interval
+    if d<1:
+        interval = long(d*10)/10.0
+        return interval, "%.1f" % interval
+    if d<10:
+        return long(d), "%d" % d
+    if d<100:
+        interval = long(d/10) * 10
+        return interval, "%d" % interval
+    if d<1000:
+        interval = long(d/100) * 100
+        return interval, "%d" % interval
+    if d<10000:
+        interval = long(d/1000) * 1000
+        return interval, "%d" % interval
+    if d<100000:
+        interval = long(d/10000) * 10000
+        return interval, "%d" % interval
+
+    return -1, ''
+

Added: packages/thuban/branches/upstream/current/Thuban/Model/session.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/session.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/session.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,452 @@
+# Copyright (c) 2001, 2002, 2003, 2004 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2102 $"
+
+import os
+from tempfile import mktemp
+import weakref
+
+from messages import MAPS_CHANGED, EXTENSIONS_CHANGED, FILENAME_CHANGED, \
+     MAP_LAYERS_CHANGED, MAP_PROJECTION_CHANGED, \
+     LAYER_CHANGED, LAYER_PROJECTION_CHANGED, LAYER_VISIBILITY_CHANGED,\
+     EXTENSION_CHANGED, EXTENSION_OBJECTS_CHANGED, CHANGED, \
+     TABLE_REMOVED, DBCONN_ADDED, DBCONN_REMOVED
+
+from Thuban import _
+
+from base import TitledObject, Modifiable
+from map import Map
+from data import ShapefileStore
+from table import DBFTable
+import postgisdb
+
+from transientdb import TransientDatabase, AutoTransientTable
+
+class AutoRemoveFile:
+
+    """Remove a file once all references go away."""
+
+    def __init__(self, filename, tempdir = None):
+        """Initialize the AutoRemoveFile
+
+        Parameters:
+           filename -- The name of the file to remove in __del__
+           tempdir -- Another object simple stored as an instance variable.
+
+        As the name suggests the tempdir parameter is intended for a
+        temporary directory the file might be located in. The intended
+        use is that it's an instance of AutoRemoveDir.
+        """
+        self.filename = filename
+        self.tempdir = tempdir
+
+    def __del__(self, remove = os.remove):
+        remove(self.filename)
+
+class AutoRemoveDir:
+
+    """Remove a directory once all references go away
+
+    The intended use of this class together with AutoRemoveFile is for
+    temporary directories and files containd therein. An AutoRemoveDir
+    should be instantiated for the directory and passed as the tempdir
+    parameter to every AutoRemoveFile instance created for files in the
+    directory. An AutoRemoveFile shold be instantiated for every file
+    created in the directory so that the directory is automatically
+    removed once the last file is removed.
+    """
+
+    def __init__(self, filename):
+        """Initialize the AutoRemoveDir
+
+        The parameter is the name of the directory.
+        """
+        self.filename = filename
+
+    def __del__(self, rmdir = os.rmdir):
+        rmdir(self.filename)
+
+
+# WeakKey dictionary mapping objects like the transient_db to
+# AutoRemoveDir or AutoRemoveFile instances to make sure that the
+# temporary files and the directory are deleted but not before the
+# objects that use them go away.
+auto_remover = weakref.WeakKeyDictionary()
+
+class Session(TitledObject, Modifiable):
+
+    """A complete session.
+
+    A Session consists of arbitrary numbers of maps, tables and extensions
+
+    Session objects send the following events:
+
+        TITLE_CHANGED -- The title has changed. Parameters: the session.
+
+        FILENAME_CHANGED -- The filename has changed. No parameters.
+
+        MAPS_CHANGED -- Maps were added, removed.
+
+        EXTENSIONS_CHANGED -- Extensions were added, removed.
+
+        MAP_LAYERS_CHANGED -- Same as the map's event of the same name.
+                          It's simply resent from the session to make
+                          subscriptions easier.
+
+        CHANGED -- Generic changed event. Parameters: the session. The
+                   event is always issued when any other changed event
+                   is issused. This is useful for code that needs to be
+                   notified whenever something in the session has
+                   changed but it's too cumbersome or error-prone to
+                   subscribe to all the individual events.
+    """
+
+    # message channels that have to be forwarded from maps contained in
+    # the session.
+    forwarded_channels = (
+        # generic channels
+        CHANGED,
+
+        # map specific channels
+        MAP_PROJECTION_CHANGED,
+        MAP_LAYERS_CHANGED,
+
+        # layer channels forwarded by the map
+        LAYER_PROJECTION_CHANGED,
+        LAYER_CHANGED,
+        LAYER_VISIBILITY_CHANGED,
+
+        # channels forwarded by an extension
+        EXTENSION_CHANGED,
+        EXTENSION_OBJECTS_CHANGED)
+
+    def __init__(self, title):
+        TitledObject.__init__(self, title)
+        Modifiable.__init__(self)
+        self.filename = None
+        self.maps = []
+        self.tables = []
+        self.shapestores = []
+        self.extensions = []
+        self.db_connections = []
+        self.temp_dir = None
+        self.transient_db = None
+
+    def changed(self, channel = None, *args):
+        """Like the inherited version but issue a CHANGED message as well.
+
+        The CHANGED message is only issued if channel given is a
+        different channel than CHANGED.
+        """
+        Modifiable.changed(self, channel, *args)
+        if channel != CHANGED:
+            self.issue(CHANGED, self)
+
+    def SetFilename(self, filename):
+        self.filename = filename
+        self.changed(FILENAME_CHANGED)
+
+    def Maps(self):
+        return self.maps
+
+    def HasMaps(self):
+        return len(self.maps) > 0
+
+    def AddMap(self, map):
+        self.maps.append(map)
+        for channel in self.forwarded_channels:
+            map.Subscribe(channel, self.forward, channel)
+        self.changed(MAPS_CHANGED)
+
+    def RemoveMap(self, map):
+        for channel in self.forwarded_channels:
+            map.Unsubscribe(channel, self.forward, channel)
+        self.maps.remove(map)
+        self.changed(MAPS_CHANGED)
+        map.Destroy()
+
+    def Extensions(self):
+        return self.extensions
+
+    def HasExtensions(self):
+        return len(self.extensions) > 0
+
+    def AddExtension(self, extension):
+        self.extensions.append(extension)
+        for channel in self.forwarded_channels:
+            extension.Subscribe(channel, self.forward, channel)
+        self.changed(EXTENSIONS_CHANGED)
+
+    def ShapeStores(self):
+        """Return a list of all ShapeStore objects open in the session"""
+        return [store() for store in self.shapestores]
+
+    def _add_shapestore(self, store):
+        """Internal: Add the shapestore to the list of shapestores"""
+        self.shapestores.append(weakref.ref(store,
+                                            self._clean_weak_store_refs))
+
+    def _clean_weak_store_refs(self, weakref):
+        """Internal: Remove the weakref from the shapestores list"""
+        self.shapestores = [store for store in self.shapestores
+                                  if store is not weakref]
+
+    def Tables(self):
+        """Return a list of all table objects open in the session
+
+        The list includes all tables that are indirectly opened through
+        shape stores and the tables that have been opened explicitly.
+        """
+        tables = self.tables[:]
+        ids = {}
+        for t in tables:
+            ids[id(t)] = 1
+        for store in self.ShapeStores():
+            t = store.Table()
+            if id(t) not in ids:
+                ids[id(t)] = 1
+                tables.append(t)
+        return tables
+
+    def UnreferencedTables(self):
+        """Return the tables that are not referenced by other data sources"""
+        known = {}
+        for table in self.tables:
+            known[id(table)] = 0
+        for table in self.tables + self.ShapeStores():
+            for dep in table.Dependencies():
+                known[id(dep)] = 1
+        return [table for table in self.tables if known[id(table)] == 0]
+
+    def AddTable(self, table):
+        """Add the table to the session
+
+        All tables associated with the session that are not implicitly
+        created by the OpenShapefile method (and maybe other Open*
+        methods in the future) have to be passed to this method to make
+        sure the session knows about it. The session keeps a reference
+        to the table. Only tables managed by the session in this way
+        should be used for layers contained in one of the session's
+        maps.
+
+        The table parameter may be any object implementing the table
+        interface. If it's not already one of the transient tables
+        instantiate an AutoTransientTable with it and use that instead
+        of the original table (note that the AutoTransientTable keeps a
+        reference to the original table).
+
+        Return the table object actually used by the session.
+        """
+        if not hasattr(table, "transient_table"):
+            transient_table = AutoTransientTable(self.TransientDB(), table)
+        else:
+            transient_table = table
+        self.tables.append(transient_table)
+        self.changed()
+        return transient_table
+
+    def RemoveTable(self, table):
+        """Remove the table from the session.
+
+        The table object must be a table object previously returned by
+        the AddTable method. If the table is not part of the session
+        raise a ValueError.
+
+        Issue a TABLE_REMOVED message after the table has been removed.
+        The message has the removed table as the single parameter.
+        """
+        tables = [t for t in self.tables if t is not table]
+        if len(tables) == len(self.tables):
+            raise ValueError
+        self.tables = tables
+        self.changed(TABLE_REMOVED, table)
+
+    def DataContainers(self):
+        """Return all data containers, i.e. shapestores and tables"""
+        return self.tables + self.ShapeStores()
+
+    def OpenTableFile(self, filename):
+        """Open the table file filename and return the table object.
+
+        The filename argument must be the name of a DBF file.
+        """
+        return self.AddTable(DBFTable(filename))
+
+    def temp_directory(self):
+        """
+        Return the name of the directory for session specific temporary files
+
+        Create the directory if it doesn't exist yet.
+        """
+        if self.temp_dir is None:
+            temp_dir = mktemp()
+            os.mkdir(temp_dir, 0700)
+            self.temp_dir = temp_dir
+            self.temp_dir_remover = AutoRemoveDir(self.temp_dir)
+        return self.temp_dir
+
+    def OpenShapefile(self, filename):
+        """Return a shapefile store object for the data in the given file"""
+        store = ShapefileStore(self, filename)
+        self._add_shapestore(store)
+        return store
+
+    def AddShapeStore(self, shapestore):
+        """Add the shapestore to the session.
+
+        The session only holds a weak reference to the shapestore, so it
+        will automatically be removed from the session when the last
+        reference goes away.
+        """
+        self._add_shapestore(shapestore)
+        return shapestore
+
+    def TransientDB(self):
+        if self.transient_db is None:
+            filename = os.path.join(self.temp_directory(), "transientdb")
+            self.transient_db = TransientDatabase(filename)
+            #print self.temp_dir_remover
+            auto_remover[self.transient_db] = AutoRemoveFile(filename,
+                                                        self.temp_dir_remover)
+        return self.transient_db
+
+    def AddDBConnection(self, dbconn):
+        """Add the database connection dbconn to the session
+
+        The argument should be an instance of PostGISConnection.
+        """
+        self.db_connections.append(dbconn)
+        self.changed(DBCONN_ADDED)
+
+    def DBConnections(self):
+        """
+        Return a list of all database connections registered with the session
+        """
+        return self.db_connections
+
+    def HasDBConnections(self):
+        """Return whether the session has open database connections"""
+        return bool(self.db_connections)
+
+    def CanRemoveDBConnection(self, dbconn):
+        """Return whether the database connections dbconn can be removed
+
+        If can be removed if none of the shapestores or tables in the
+        session references it.
+        """
+        for store in self.ShapeStores():
+            if (isinstance(store, postgisdb.PostGISShapeStore)
+                and store.db is dbconn):
+                return 0
+        for table in self.Tables():
+            if (isinstance(table, postgisdb.PostGISTable)
+                and table.db is dbconn):
+                return 0
+        return 1
+
+    def RemoveDBConnection(self, dbconn):
+        """Remove the database connection from the session
+
+        The parameter must be a connection that was registered
+        previously by a AddDBConnection() call.
+        """
+        if self.CanRemoveDBConnection(dbconn):
+            remaining = [c for c in self.db_connections if c is not dbconn]
+            if len(remaining) < len(self.db_connections):
+                self.db_connections = remaining
+                self.changed(DBCONN_REMOVED)
+            else:
+                raise ValueError("DBConection %r is not registered"
+                                 " with session %r" % (dbconn, self))
+        else:
+            raise ValueError("DBConnection %r is still in use" % (dbconn,))
+
+    def OpenDBShapeStore(self, db, tablename, id_column = None,
+                         geometry_column = None):
+        """Create and return a shapstore for a table in the database
+
+        The db parameter must be a database connection previously passed
+        to AddDBConnection().
+        """
+        store = postgisdb.PostGISShapeStore(db, tablename,
+                                            id_column = id_column,
+                                            geometry_column = geometry_column)
+        self._add_shapestore(store)
+        return store
+
+    def Destroy(self):
+        for map in self.maps:
+            map.Destroy()
+        self.maps = []
+        self.tables = []
+        Modifiable.Destroy(self)
+
+        # Close the transient DB explicitly so that it removes any
+        # journal files from the temporary directory
+        if self.transient_db is not None:
+            self.transient_db.close()
+
+    def forward(self, *args):
+        """Reissue events.
+
+        If the channel the event is forwarded to is a changed-channel
+        that is not the CHANGED channel issue CHANGED as well. An
+        channel is considered to be a changed-channel if it's name ends
+        with 'CHANGED'.
+        """
+        if len(args) > 1:
+            args = (args[-1],) + args[:-1]
+        apply(self.issue, args)
+        channel = args[0]
+        # It's a bit of a kludge to rely on the channel name for this.
+        if channel.endswith("CHANGED") and channel != CHANGED:
+            self.issue(CHANGED, self)
+
+    def WasModified(self):
+        """Return true if the session or one of the maps was modified"""
+        if self.modified:
+            return 1
+        else:
+            for map in self.maps:
+                if map.WasModified():
+                    return 1
+        return 0
+
+    def UnsetModified(self):
+        """Unset the modified flag of the session and the maps"""
+        Modifiable.UnsetModified(self)
+        for map in self.maps:
+            map.UnsetModified()
+
+    def TreeInfo(self):
+        items = []
+        if self.filename is None:
+            items.append(_("Filename:"))
+        else:
+            items.append(_("Filename: %s") % self.filename)
+
+        if self.WasModified():
+            items.append(_("Modified"))
+        else:
+            items.append(_("Unmodified"))
+
+        items.extend(self.maps)
+        items.extend(self.extensions)
+
+        return (_("Session: %s") % self.title, items)
+
+
+def create_empty_session():
+    """Return an empty session useful as a starting point"""
+    import os
+    session = Session(_('unnamed session'))
+    session.SetFilename(None)
+    session.AddMap(Map(_('unnamed map')))
+    session.UnsetModified()
+    return session

Added: packages/thuban/branches/upstream/current/Thuban/Model/table.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/table.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/table.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,524 @@
+# Copyright (c) 2001, 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Jan-Oliver Wagner <jan at intevation.de>
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Classes for handling tables of data.
+"""
+
+__version__ = "$Revision: 1961 $"
+
+import os
+import inspect
+import warnings
+
+from base import TitledObject
+
+import dbflib
+
+# the field types supported by a Table instance.
+FIELDTYPE_INT = "int"
+FIELDTYPE_STRING = "string"
+FIELDTYPE_DOUBLE = "double"
+
+
+# map the dbflib constants for the field types to our constants
+dbflib_fieldtypes = {dbflib.FTString: FIELDTYPE_STRING,
+                     dbflib.FTInteger: FIELDTYPE_INT,
+                     dbflib.FTDouble: FIELDTYPE_DOUBLE}
+
+
+class DBFColumn:
+
+    """Description of a column in a DBFTable
+
+    Instances have the following public attributes:
+
+    name -- Name of the column
+    type -- Type of the column (one of FIELDTYPE_STRING, FIELDTYPE_INT or\
+            FIELDTYPE_DOUBLE)
+    index -- The index of the column
+    width -- the width of the data in the column
+    prec -- The precision of the data (only valid for type == FIELDTYPE_DOUBLE)
+    """
+
+    def __init__(self, name, type, width, prec, index):
+        self.name = name
+        self.type = type
+        self.width = width
+        self.prec = prec
+        self.index = index
+
+
+class DBFTable(TitledObject):
+
+    """
+    Table interface for the data in a DBF file
+    """
+
+    # Implementation strategy regarding writing to a DBF file:
+    #
+    # Most of the time Thuban only needs to read from a table and it is
+    # important that Thuban can work with read-only files. Therefore the
+    # DBF file is opened only for reading initially. Only when
+    # write_record is called we try to open the DBF file for writing as
+    # well. If that succeeds the read/write DBF file will be used for
+    # all IO afterwards.
+    #
+    # It's important to use the same DBF file object for both reading
+    # and writing to make sure that reading a records after writing
+    # returns the new values. With two separate objects this wouldn't
+    # work because a DBF file object buffers some data
+
+    def __init__(self, filename):
+        self.filename = os.path.abspath(filename)
+
+        # Omit the extension in the title as it's not really needed and
+        # it can be confusing because dbflib removes extensions and
+        # appends some variations of '.dbf' before it tries to open the
+        # file. So the title could be e.g. myshapefile.shp when the real
+        # filename is myshapefile.dbf
+        title = os.path.splitext(os.path.basename(self.filename))[0]
+        TitledObject.__init__(self, title)
+
+        self.dbf = dbflib.DBFFile(filename)
+
+        # If true, self.dbf is open for writing.
+        self._writable = 0
+
+        # Create the column information objects
+        self.columns = []
+        self.column_map = {}
+        for i in range(self.NumColumns()):
+            ftype, name, width, prec = self.dbf.field_info(i)
+            ftype = dbflib_fieldtypes[ftype]
+            index = len(self.columns)
+            col = DBFColumn(name, ftype, width, prec, index)
+            self.columns.append(col)
+            self.column_map[name] = col
+            self.column_map[index] = col
+
+    def NumRows(self):
+        """Return the number of rows in the table"""
+        return self.dbf.record_count()
+
+    def NumColumns(self):
+        """Return the number of columns in the table"""
+        return self.dbf.field_count()
+
+    def Columns(self):
+        """Return the table's colum definitions
+
+        The return value is a sequence of DBFColumn instances, one for
+        each column.
+        """
+        return self.columns
+
+    def Column(self, col):
+        """Return information about the column given by its name or index
+
+        The returned object is an instance of DBFColumn
+        """
+        return self.column_map[col]
+
+    def HasColumn(self, col):
+        """Return whether the table has a column with the given name or index
+        """
+        return self.column_map.has_key(col)
+
+    def RowIdToOrdinal(self, gid):
+        """Return the row ordinal given its id
+
+        Since for DBFTables the row id is the row number, return the
+        value unchanged.
+        """
+        return gid
+
+    def RowOrdinalToId(self, num):
+        """Return the rowid for given its ordinal
+
+        Since for DBFTables the row id is the row number, return the
+        value unchanged.
+        """
+        return num
+
+    def ReadRowAsDict(self, row, row_is_ordinal = 0):
+        """Return the entire row as a dictionary with column names as keys
+
+        The row_is_ordinal is ignored for DBF tables because the row id
+        is always the row number.
+        """
+        return self.dbf.read_record(row)
+
+    def ReadValue(self, row, col, row_is_ordinal = 0):
+        """Return the value of the specified row and column
+
+        The col parameter may be the index of the column or its name.
+
+        The row_is_ordinal is ignored for DBF tables because the row id
+        is always the row number.
+        """
+        return self.dbf.read_attribute(row, self.column_map[col].index)
+
+    def ValueRange(self, col):
+        """Return the minimum and maximum values of the values in the column
+
+        The return value is a tuple (min, max) unless the table is empty
+        in which case the return value is None.
+        """
+        count = self.NumRows()
+
+        if count == 0:
+            return None
+
+        min = max = self.ReadValue(0, col)
+        for i in range(1, count):
+            value = self.ReadValue(i, col)
+            if value < min:
+                min = value
+            elif value > max:
+                max = value
+
+        return (min, max)
+
+    def UniqueValues(self, col):
+        """Return a sorted list of all unique values in the column col"""
+        dict = {}
+
+        for i in range(self.NumRows()):
+            value = self.ReadValue(i, col)
+            dict[value] = 0
+
+        values = dict.keys()
+        values.sort()
+        return values
+
+    def Dependencies(self):
+        """Return an empty sequence. The DBFTable doesn't depend on anything"""
+        return ()
+
+    # DBF specific interface parts.
+
+    def Width(self, col):
+        """Return column width"""
+        return self.column_map[col].width
+
+    def Destroy(self):
+        self.dbf.close()
+        self.dbf = None
+
+    def write_record(self, record, values):
+        """Write the values into the record
+
+        The values parameter may either be a dictionary or a sequence.
+
+        If it's a dictionary the keys must be the names of the fields
+        and their value must have a suitable type. Only the fields
+        actually contained in the dictionary are written. Fields for
+        which there's no item in the dict are not modified.
+
+        If it's a sequence, all fields must be present in the right
+        order.
+        """
+        if not self._writable:
+            new_dbf = dbflib.DBFFile(self.filename, "r+b")
+            self.dbf.close()
+            self.dbf = new_dbf
+            self._writable = 1
+        self.dbf.write_record(record, values)
+        self.dbf.commit()
+
+    def FileName(self):
+        """Return the filename the DBFTable was instantiated with"""
+        return self.filename
+
+
+class MemoryColumn:
+
+    def __init__(self, name, type, index):
+        self.name = name
+        self.type = type
+        self.index = index
+
+class MemoryTable(TitledObject):
+
+    """Very simple table implementation that operates on a list of tuples"""
+
+    def __init__(self, fields, data):
+        """Initialize the MemoryTable
+
+        Parameters:
+        fields -- List of (name, field_type) pairs
+        data -- List of tuples, one for each row of data
+        """
+        self.data = data
+        title = 'MemoryTable'
+        TitledObject.__init__(self, title)
+
+        # Create the column information objects
+        self.columns = []
+        self.column_map = {}
+        for name, ftype in fields:
+            index = len(self.columns)
+            col = MemoryColumn(name, ftype, index)
+            self.columns.append(col)
+            self.column_map[name] = col
+            self.column_map[index] = col
+
+    def NumColumns(self):
+        """Return the number of columns in the table"""
+        return len(self.columns)
+
+    def Column(self, col):
+        """Return information about the column given by its name or index
+
+        The returned object is an instance of MemoryColumn.
+        """
+        return self.column_map[col]
+
+    def Columns(self):
+        """Return the table's colum definitions
+
+        The return value is a sequence of MemoryColumn instances, one
+        for each column.
+        """
+        return self.columns
+
+    def HasColumn(self, col):
+        """Return whether the table has a column with the given name or index
+        """
+        return self.column_map.has_key(col)
+
+    def NumRows(self):
+        """Return the number of rows in the table"""
+        return len(self.data)
+
+    def RowIdToOrdinal(self, gid):
+        """Return the row ordinal given its id
+
+        Since for MemoryTables the row id is the row number, return the
+        value unchanged.
+        """
+        return gid
+
+    def RowOrdinalToId(self, num):
+        """Return the rowid for given its ordinal
+
+        Since for MemoryTables the row id is the row number, return the
+        value unchanged.
+        """
+        return num
+
+    def ReadValue(self, row, col, row_is_ordinal = 0):
+        """Return the value of the specified row and column
+
+        The col parameter may be the index of the column or its name.
+
+        The row_is_ordinal is ignored for DBF tables because the row id
+        is always the row number.
+        """
+        return self.data[row][self.column_map[col].index]
+
+    def ReadRowAsDict(self, index, row_is_ordinal = 0):
+        """Return the entire row as a dictionary with column names as keys
+
+        The row_is_ordinal is ignored for DBF tables because the row id
+        is always the row number.
+        """
+        return dict([(col.name, self.data[index][col.index])
+                      for col in self.columns])
+
+    def ValueRange(self, col):
+        """Return the minimum and maximum values of the values in the column
+
+        The return value is a tuple (min, max) unless the table is empty
+        in which case the return value is None.
+        """
+
+        index = self.column_map[col].index
+        values = [row[index] for row in self.data]
+        if not values:
+            return None
+
+        return min(values), max(values)
+
+    def UniqueValues(self, col):
+        """Return a sorted list of all unique values in the column col
+
+        col can be either column index or name.
+        """
+        dict = {}
+
+        for i in range(self.NumRows()):
+            value = self.ReadValue(i, col)
+            dict[value] = 0
+
+        values = dict.keys()
+        values.sort()
+        return values
+
+    def Width(self, col):
+        """Return the maximum width of values in the column
+
+        The return value is the the maximum length of string
+        representation of the values in the column (represented by index
+        or name).
+        """
+        max = 0
+
+        type  = self.column_map[col].type
+        index = self.column_map[col].index
+        values = [row[index] for row in self.data]
+        if not values:
+            return None
+
+        if type == FIELDTYPE_DOUBLE:
+            format = "%.12f"
+        elif type == FIELDTYPE_INT:
+            format = "%d"
+        else:
+            format = "%s"
+        for value in values:
+            l = len(format % value)
+            if l > max:
+                max = l
+
+        return max
+
+    def Dependencies(self):
+        """Return an empty sequence. The MemoryTable doesn't depend on anything
+        """
+        return ()
+
+    def write_record(self, record, values):
+        # TODO: Check for correct lenght and perhaps also
+        # for correct types in case values is a tuple. How to report problems?
+        # TODO: Allow values to be a dictionary and write the single
+        # fields that are specified.
+        self.data[record] = values
+
+
+
+def _find_dbf_column_names(names):
+    """Determine the column names to use in a DBF file
+
+    DBF files have a length limit of 10 characters on the column names
+    so when writing an arbitrary Thuban table to a DBF file we may have
+    we may have to rename some of the columns making sure that they're
+    unique in the DBF file too.
+
+    Names that are already short enough will stay the same. Longer names
+    will be truncated to 10 characters or if that isn't unique it will
+    be truncated more and filled up with digits.
+
+    The parameter names should be a list of the column names. The return
+    value will be a dictionary mapping the names in the input list to
+    the names to use in the DBF file.
+    """
+    # mapping from the original names in table to the names in the DBF
+    # file
+    name_map = {}
+
+    # First, we keep all names that are already short enough
+    for i in range(len(names) - 1, -1, -1):
+        if len(names[i]) <= 10:
+            name_map[names[i]] = names[i]
+            del names[i]
+
+    # dict used as a set of all names already used as DBF column names
+    used = name_map.copy()
+
+    # Go through all longer names. If the name truncated to 10
+    # characters is not used already, we use that. Otherwise we truncate
+    # it more and append numbers until we get an unused name
+    for name in names:
+        truncated = name[:10]
+        num = 0; numstr = ""
+        #print "truncated", truncated, num
+        while truncated in used and len(numstr) < 10:
+            num += 1
+            numstr = str(num)
+            truncated = name[:10 - len(numstr)] + numstr
+            #print "truncated", truncated, num
+        if len(numstr) >= 10:
+            # This case should never happen in practice as tables with
+            # 10^10 columns seem very unlikely :)
+            raise ValueError("Can't find unique dbf column name")
+
+        name_map[name] = truncated
+        used[truncated] = 1
+
+    return name_map
+
+def table_to_dbf(table, filename, rows = None):
+    """Create the dbf file filename from the table.
+    
+    If rows is not None (the default) then it must be a list of row
+    indices to be saved to the file, otherwise all rows are saved.
+    """
+
+    dbf = dbflib.create(filename)
+
+    dbflib_fieldtypes = {FIELDTYPE_STRING: dbflib.FTString,
+                         FIELDTYPE_INT: dbflib.FTInteger,
+                         FIELDTYPE_DOUBLE: dbflib.FTDouble}
+
+
+    name_map = _find_dbf_column_names([col.name for col in table.Columns()])
+
+    # Initialise the header. Distinguish between DBFTable and others.
+    for col in table.Columns():
+        width = table.Width(col.name)
+        if col.type == FIELDTYPE_DOUBLE:
+            prec = getattr(col, "prec", 12)
+        else:
+            prec = 0
+        dbf.add_field(name_map[col.name], dbflib_fieldtypes[col.type],
+                      width, prec)
+
+    if rows is None:
+        rows = range(table.NumRows())
+
+    recNum = 0
+    for i in rows:
+        record = {}
+        for key, value in table.ReadRowAsDict(i).items():
+            record[name_map[key]] = value
+        dbf.write_record(recNum, record)
+        recNum += 1
+    dbf.close()
+
+def table_to_csv(table, filename, rows = None):
+    """Export table to csv file.
+    
+    If rows is not None (the default) then it must be a list of row
+    indices to be saved to the file, otherwise all rows are saved.
+    """
+
+    file = open(filename,"w")
+    columns = table.Columns()
+    if columns:
+        header = "#%s" % columns[0].name
+        for col in columns[1:]:
+            header = header + ",%s" % col.name
+        header = header + "\n"
+        file.write(header)
+
+        if rows is None:
+            rows = range(table.NumRows())
+
+        for i in rows:
+            record = table.ReadRowAsDict(i)
+            if len(record):
+                line = "%s" % record[columns[0].name]
+                for col in columns[1:]:
+                    line = line + ",%s" % record[col.name]
+            line = line + "\n"
+            file.write(line)
+    file.close()
+

Added: packages/thuban/branches/upstream/current/Thuban/Model/transientdb.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/transientdb.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/transientdb.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,700 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Database for transient data
+
+This database is intended for data representations needed during the
+lifetime of a Thuban session but which is not permanent. Examples of
+this are for instance a join of two DBF files where the DBF files are
+the permanent representation of the data and the join only exists in the
+Thuban session and is reconstructed when the session is opened.
+"""
+
+__version__ = "$Revision: 2682 $"
+# $Source$
+# $Id: transientdb.py 2682 2006-05-15 20:11:15Z dpinte $
+
+# Pysqlite version 1. and 2. behaves quiet differently
+# Pysqlite uses a different paramstyle.  The older version
+# support format and pyformat while pysqlite2 supports only qmark
+# and named.
+# The sqlite2 boolean variable is used to manage specific part of the code
+try:
+      # Using SQLITE 2.x
+    sqlite2 = True
+    from pysqlite2 import dbapi2 as sqlite
+except ImportError:
+      # Using SQLITE 1.x
+    sqlite2 = False
+    import sqlite
+    
+
+from base import TitledObject
+
+import table
+
+sql_type_map = {
+    table.FIELDTYPE_INT: "INTEGER",
+    table.FIELDTYPE_STRING: "VARCHAR",
+    table.FIELDTYPE_DOUBLE: "FLOAT",
+    }
+
+type_converter_map = {
+    table.FIELDTYPE_INT: int,
+    table.FIELDTYPE_STRING: str,
+    table.FIELDTYPE_DOUBLE: float,
+    }
+
+class TransientDatabase:
+
+    def __init__(self, filename):
+        self.filename = filename
+        self.conn = sqlite.connect(filename)
+        # Counters to produce unique table and column names
+        self.num_tables = 0
+        self.num_cols = 0
+        # Since there's only once process using the SQLite database, we
+        # might be able to get a tad more speed with default_synchronous
+        # OFF. So far I haven't seen any measurable speedup, though.
+        #self.execute("PRAGMA default_synchronous = OFF")
+
+    def __del__(self):
+        self.close()
+
+    def close(self):
+        if self.conn is not None:
+            self.conn.close()
+            self.conn = None
+
+    def new_table_name(self):
+        self.num_tables += 1
+        return "Table%03d" % self.num_tables
+
+    def new_column_name(self):
+        self.num_cols += 1
+        return "Col%03d" % self.num_cols
+
+    def execute(self, *args):
+        """execute the SQL statement in the database and return the result"""
+        cursor = self.conn.cursor()
+        cursor.execute(*args)
+        result = cursor.fetchone()
+        self.conn.commit()
+        return result
+
+    def cursor(self):
+        return self.conn.cursor()
+
+
+class ColumnReference:
+
+    def __init__(self, name, type, internal_name):
+        self.name = name
+        self.type = type
+        self.internal_name = internal_name
+
+
+class TransientTableBase:
+
+    """Base class for tables in the transient database"""
+
+    def __init__(self, transient_db):
+        """Initialize the table for use with the given transient db"""
+        self.db = transient_db
+        self.tablename = self.db.new_table_name()
+        self.indexed_columns = {}
+        self.read_record_cursor = None
+        self.read_record_last_row = None
+        self.read_record_last_result = None
+
+    def create(self, columns):
+        self.columns = columns
+        self.name_to_column = {}
+        self.orig_names = []
+        self.internal_to_orig = {}
+        self.orig_to_internal = {}
+        self.column_map = {}
+
+        # Create the column objects and fill various maps and lists
+        for index in range(len(self.columns)):
+            col = self.columns[index]
+            self.name_to_column[col.name] = col
+            self.orig_names.append(col.name)
+            self.internal_to_orig[col.internal_name] = col.name
+            self.orig_to_internal[col.name] = col.internal_name
+            self.column_map[col.name] = col
+            self.column_map[index] = col
+
+        # Build the CREATE TABLE statement and create the table in the
+        # database
+        table_types = ["id INTEGER PRIMARY KEY"]
+        for col in self.columns:
+            table_types.append("%s %s" % (col.internal_name,
+                                          sql_type_map[col.type]))
+        table_stmt = "CREATE TABLE %s (\n    %s\n);" % (self.tablename,
+                                                   ",\n    ".join(table_types))
+        self.db.execute(table_stmt)
+
+    def transient_table(self):
+        """
+        Return a table whose underlying implementation is in the transient db
+        """
+        return self
+
+    def ensure_index(self, column):
+        """Ensure that there's an index on the given column"""
+        if not column in self.indexed_columns:
+            internal_name = self.orig_to_internal[column]
+            indexname = "Index_%s_%s" % (self.tablename, internal_name)
+            stmt = "CREATE INDEX %s ON %s (%s);" % (indexname, self.tablename,
+                                                    internal_name)
+            self.db.execute(stmt)
+            self.indexed_columns[column] = 1
+
+    def NumColumns(self):
+        return len(self.columns)
+
+    def NumRows(self):
+        result = self.db.execute("SELECT count(*) FROM %s;" % self.tablename)
+        return int(result[0])
+
+    def Columns(self):
+        return self.columns
+
+    def Column(self, col):
+        return self.column_map[col]
+
+    def HasColumn(self, col):
+        """Return whether the table has a column with the given name or index
+        """
+        return self.column_map.has_key(col)
+
+    def RowIdToOrdinal(self, gid):
+        """Return the row ordinal given its id
+
+        At the moment the transient tables are only used for tables that
+        don't distinguish between row number and row id, so the value is
+        returned unchanged.
+        """
+        return gid
+
+    def RowOrdinalToId(self, num):
+        """Return the rowid for given its ordinal
+
+        At the moment the transient tables are only used for tables that
+        don't distinguish between row number and row id, so the value is
+        returned unchanged.
+        """
+        return num
+
+    def ReadRowAsDict(self, index, row_is_ordinal = 0):
+        """Return the entire row as a dictionary with column names as keys
+
+        The row_is_ordinal is ignored because at the moment the
+        transient tables are only used for DBF files where it doesn't
+        matter.
+        """
+        # Implementation Strategy: Executing a completely new select
+        # statement every time this method is called is too slow. The
+        # most important usage is to read the records more or less
+        # sequentially. This happens e.g. when drawing a layer with a
+        # classification where the shapes are drawn in order of the
+        # shape ids. Another pattern is that the same row is requested
+        # several times in a row. This happens in the table view, for
+        # instance.
+
+        # We can exploit this to make access faster by having one cursor
+        # open all the time and keeping the last row read around in case
+        # the same row is accessed again the next time and if the row
+        # index is larger than the row we have read last we simply fetch
+        # rows from the cursor until we've reached the requested row. If
+        # the requested row index is smaller then we start a new cursor.
+
+        # FIXME: So far this scheme seems to work well enough. Obvious
+        # improvements would be to start the cursor at exactly the
+        # requested row (should be efficient and easy to do now that the
+        # id is the primary key) and to perhaps to also start a new
+        # cursor if the requested index is much larger than the last row
+        # so that we don't read and discard lots of the rows.
+
+        # Check whether we have to start a new cursor
+        if self.read_record_cursor is None or index <self.read_record_last_row:
+            stmt = ("SELECT %s FROM %s;"
+                    % (", ".join([c.internal_name for c in self.columns]),
+                       self.tablename))
+            self.read_record_cursor = self.db.cursor()
+            self.read_record_cursor.execute(stmt)
+            self.read_record_last_row = -1
+            self.read_record_last_result = None
+
+        # Now we should have a cursor at a position less than or equal
+        # to the index so the following if statement will always set
+        # result to a suitable value
+        assert index >= self.read_record_last_row
+
+        if index == self.read_record_last_row:
+            result = self.read_record_last_result
+        else:
+            for i in range(index - self.read_record_last_row):
+                result = self.read_record_cursor.fetchone()
+                self.read_record_last_result = result
+        self.read_record_last_row = index
+        return dict(zip(self.orig_names, result))
+
+    def ReadValue(self, row, col, row_is_ordinal = 0):
+        """Return the value of the specified row and column
+
+        The col parameter may be the index of the column or its name.
+
+        The row_is_ordinal is ignored because at the moment the
+        transient tables are only used for DBF files where it doesn't
+        matter.
+        """
+        # Depending on the actual access patterns of the table data, it
+        # might be a bit faster in some circumstances to not implement
+        # this via ReadRowAsDict, but this simple implementation should
+        # be fast enough for most purposes.
+        return self.ReadRowAsDict(row)[self.column_map[col].name]
+
+    def ValueRange(self, col):
+        # Performance notes:
+        #
+        # In sqlite 2.8.6 the min and max aggregate functions can use an
+        # index but only when used as the only expression in the select
+        # statement (i.e. 'select min(col), max(col) from tbl;' will not
+        # use the index but 'select min(col) from tbl;' will) so we
+        # query the minimum and maximum separately.
+        #
+        # With the separate statements we can take advantage of an index
+        # if it exists. If the index doesn't exist, creating it first
+        # and then using it in the query is slower than the queries
+        # without an index. Creating the index is only an advantage if
+        # the queries are performed multiple times. With the current use
+        # patterns where ValueRange is only used occasionally by the
+        # classification generation dialog creating the index only for
+        # this usage is not really worth it, so we don't.
+        col = self.column_map[col]
+        iname = col.internal_name
+        min = self.db.execute("SELECT min(%s) FROM %s;"
+                              % (iname, self.tablename))[0]
+        max = self.db.execute("SELECT max(%s) FROM %s;"
+                              % (iname, self.tablename))[0]
+        converter = type_converter_map[col.type]
+        return (converter(min), converter(max))
+
+    def UniqueValues(self, col):
+        # Performance notes:
+        #
+        # In sqlite 2.8.6 there doesn't seem to be a way to query the
+        # unique items that uses an index. I've tried
+        #
+        #   SELECT col FROM tbl GROUP BY col;
+        #
+        # and
+        #
+        #   SELECT DISTINCT col FROM tbl;
+        #
+        # and in both cases the index is not used. If the index isn't
+        # used it doesn't make sense to call self.ensure_index.
+        iname = self.column_map[col].internal_name
+        cursor = self.db.cursor()
+        cursor.execute("SELECT %s FROM %s GROUP BY %s;"
+                       % (iname, self.tablename, iname))
+        result = []
+        while 1:
+            row = cursor.fetchone()
+            if row is None:
+                break
+            result.append(row[0])
+        return result
+
+    def Width(self, col):
+        """Return the maximum width of values in the column
+
+        The return value is the the maximum length of string
+        representation of the values in the column (represented by index
+        or name).
+        """
+        max = 0
+
+        type  = self.column_map[col].type
+        iname = self.column_map[col].internal_name
+        cursor = self.db.cursor()
+        cursor.execute("SELECT %s FROM %s;" % (iname, self.tablename))
+        values = [ i[0] for i in cursor.fetchall()]
+        if not values:
+            return None
+
+        if type == table.FIELDTYPE_DOUBLE:
+            format = "%.12f"
+        elif type == table.FIELDTYPE_INT:
+            format = "%d"
+        else:
+            format = "%s"
+        for value in values:
+            if value is None: continue
+            l = len(format % value)
+            if l > max:
+                max = l
+
+        return max
+
+    def SimpleQuery(self, left, comparison, right):
+        """Return the indices of all rows that matching a condition.
+
+        Parameters:
+           left -- The column object for the left side of the comparison
+
+           comparison -- The comparison operator as a string. It must be
+                         one of '==', '!=', '<', '<=', '>=', '>'
+
+           right -- The right hand side of the comparison. It must be
+                    either a column object or a value, i.e. a string,
+                    int or float.
+
+        The return value is a sorted list of the indices of the rows
+        where the condition is true.
+        """
+        if comparison not in ("==", "!=", "<", "<=", ">=", ">"):
+            raise ValueError("Comparison operator %r not allowed" % comparison)
+
+        if hasattr(right, "internal_name"):
+            right_template = right.internal_name
+            params = ()
+        else:
+            if sqlite2:
+                right_template = "?"
+            else: right_template = "%s"
+            params = (right,)
+
+        query = "SELECT id FROM %s WHERE %s %s %s ORDER BY id;" \
+                % (self.tablename, left.internal_name, comparison,
+                   right_template)
+
+        cursor = self.db.cursor()
+        cursor.execute(query, params)
+        result = []
+        while 1:
+            row = cursor.fetchone()
+            if row is None:
+                break
+            result.append(row[0])
+        return result
+
+    def Dependencies(self):
+        """Placeholder for a method in a derived class.
+
+        Return a sequence with the tables and other data objects that
+        self depends on.
+        """
+        raise NotImplementedError
+
+
+class TransientTable(TitledObject, TransientTableBase):
+
+    """A Table in a transient DB that starts as the copy of a Thuban Table."""
+
+    def __init__(self, transient_db, table):
+        """Create a new table in the given transient DB as a copy of table
+
+        The table argument can be any object implementing the Table
+        interface.
+        """
+        TransientTableBase.__init__(self, transient_db)
+        TitledObject.__init__(self, table.Title())
+        self.create(table)
+
+    def create(self, table):
+        columns = []
+        for col in table.Columns():
+            columns.append(ColumnReference(col.name, col.type,
+                                           self.db.new_column_name()))
+        TransientTableBase.create(self, columns)
+
+        # copy the input table to the transient db
+
+        # A key to insert to use for the formatting of the insert
+        # statement. The key must not be equal to any of the column
+        # names so we construct one by building a string of x's that is
+        # longer than any of the column names
+        id_key = max([len(col.name) for col in self.columns]) * "x"
+
+        if sqlite2:
+            insert_template = "INSERT INTO %s (id, %s) VALUES (%s, %s);" \
+                               % (self.tablename,
+                                  ", ".join([col.internal_name
+                                             for col in self.columns]),
+                                  '?',
+                                  ", ".join(["?" for col in self.columns]))
+
+        else:
+            insert_template = "INSERT INTO %s (id, %s) VALUES (%%(%s)s, %s);" \
+                               % (self.tablename,
+                                  ", ".join([col.internal_name
+                                             for col in self.columns]),
+                                  id_key,
+                                  ", ".join(["%%(%s)s" % col.name
+                                             for col in self.columns]))
+        cursor = self.db.cursor()
+        for i in range(table.NumRows()):
+            row = table.ReadRowAsDict(i)
+            row[id_key] = i
+            if sqlite2:
+                params = [i]
+                for col in self.columns:
+                  params.append(row[col.name])
+                cursor.execute(insert_template, params)
+            else:  
+                cursor.execute(insert_template, row)
+        self.db.conn.commit()
+
+
+
+class TransientJoinedTable(TitledObject, TransientTableBase):
+
+    """A Table in the transient DB that contains a join of two tables"""
+
+    def __init__(self, transient_db, left_table, left_field,
+                 right_table, right_field = None, outer_join = False):
+        """Create a new table in the transient DB as a join of two tables.
+
+        Both input tables, left_table and right_table must have a
+        transient_table method that returns a table object for a table
+        in the transient database. The join is performed on the condition
+        that the value of the left_field column the the left table is
+        equal to the value of the right_field in the right_table.
+
+        The joined table contains all columns of the input tables,
+        however, the column names of the right table may be changed
+        slightly to make them unique in the joined table. This is
+        currently done by appending a sufficient number of underscores
+        ('_').
+        """
+        TransientTableBase.__init__(self, transient_db)
+        self.dependencies = (left_table, right_table)
+        self.left_table = left_table.transient_table()
+        self.left_field = left_field
+        self.right_table = right_table.transient_table()
+        if right_field:
+            self.right_field = right_field
+        else:
+            self.right_field = self.left_field
+        self.outer_join = outer_join
+
+        title = "Join of %(left)s and %(right)s" \
+                % {"left": self.left_table.Title(),
+                   "right": self.right_table.Title()}
+        TitledObject.__init__(self, title)
+
+        self.create()
+
+    def create(self):
+        """Internal: Create the table with the joined data"""
+        self.tablename = self.db.new_table_name()
+
+        self.right_table.ensure_index(self.right_field)
+
+        # determine the internal column names to join on before
+        # coalescing the column information because if the external
+        # column names are the same they will be mapped to the same
+        # internal name afterwards.
+        internal_left_col = self.left_table.orig_to_internal[self.left_field]
+        internal_right_col =self.right_table.orig_to_internal[self.right_field]
+
+        # Coalesce the column information
+        visited = {}
+        columns = []
+        newcolumns = []
+        for table in (self.left_table, self.right_table):
+            for col in table.Columns():
+                colname = col.name
+                # We can't allow multiple columns with the same
+                # original name, so append '_' to this one until
+                # it is unique.
+                # FIXME: There should be a better solution.
+                while colname in visited:
+                    colname = colname + '_'
+                columns.append((table.tablename, col))
+                newcol = ColumnReference(colname, col.type,
+                                            "Col%03d" % (len(newcolumns)+1))
+                newcolumns.append(newcol)
+                visited[colname] = 1
+        TransientTableBase.create(self, newcolumns)
+
+        # Copy the joined data to the table.
+        newinternal_names = [col.internal_name for col in self.columns]
+        internal_references = ["%s.%s" % (table, col.internal_name) 
+                                                    for table, col in columns]
+        if self.outer_join:
+            join_operator = 'LEFT OUTER JOIN'
+        else:
+            join_operator = 'JOIN'
+        stmt = ("INSERT INTO %s (id, %s) SELECT %s.id, %s FROM %s"
+                " %s %s ON %s.%s = %s.%s;"
+                % (self.tablename,
+                   ", ".join(newinternal_names),
+                   self.left_table.tablename,
+                   ", ".join(internal_references),
+                   self.left_table.tablename,
+                   join_operator,
+                   self.right_table.tablename,
+                   self.left_table.tablename,
+                   internal_left_col,
+                   self.right_table.tablename,
+                   internal_right_col))
+        self.db.execute(stmt)
+
+    def Dependencies(self):
+        """Return a tuple with the two tables the join depends on."""
+        return self.dependencies
+
+    def JoinType(self):
+        """Return the type of the join (either 'INNER' or 'LEFT OUTER')"""
+        if self.outer_join:
+            return "LEFT OUTER"
+        else:
+            return "INNER"
+
+
+class AutoTransientTable(TitledObject):
+
+    """Table that copies data to a transient table on demand.
+
+    The AutoTransientTable takes another table as input and copies data
+    to a table in a TransientDatabase instance on demand.
+    """
+
+    def __init__(self, transient_db, table):
+        TitledObject.__init__(self, table.Title())
+        self.transient_db = transient_db
+        self.table = table
+        self.t_table = None
+
+    def Columns(self):
+        return self.table.Columns()
+
+    def Column(self, col):
+        return self.table.Column(col)
+
+    def HasColumn(self, col):
+        """Return whether the table has a column with the given name or index
+        """
+        return self.table.HasColumn(col)
+
+    def NumRows(self):
+        return self.table.NumRows()
+
+    def NumColumns(self):
+        return self.table.NumColumns()
+
+    def RowIdToOrdinal(self, gid):
+        """Return the row ordinal given its id"""
+        if self.t_table is not None:
+            return self.t_table.RowIdToOrdinal(gid)
+        else:
+            return self.table.RowIdToOrdinal(gid)
+
+    def RowOrdinalToId(self, num):
+        """Return the rowid for given its ordinal"""
+        if self.t_table is not None:
+            return self.t_table.RowOrdinalToId(num)
+        else:
+            return self.table.RowOrdinalToId(num)
+
+    def ReadRowAsDict(self, record, row_is_ordinal = 0):
+        """Return the record no. record as a dict mapping field names to values
+        """
+        if self.t_table is not None:
+            return self.t_table.ReadRowAsDict(record,
+                                              row_is_ordinal = row_is_ordinal)
+        else:
+            return self.table.ReadRowAsDict(record,
+                                            row_is_ordinal = row_is_ordinal)
+
+    def ReadValue(self, row, col, row_is_ordinal = 0):
+        """Return the value of the specified row and column
+
+        The col parameter may be the index of the column or its name.
+        """
+        if self.t_table is not None:
+            return self.t_table.ReadValue(row, col,
+                                          row_is_ordinal = row_is_ordinal)
+        else:
+            return self.table.ReadValue(row, col,
+                                        row_is_ordinal = row_is_ordinal)
+
+    def copy_to_transient(self):
+        """Internal: Create a transient table and copy the data into it"""
+        self.t_table = TransientTable(self.transient_db, self)
+
+    def transient_table(self):
+        """
+        Return a table whose underlying implementation is in the transient db
+        """
+        if self.t_table is None:
+            self.copy_to_transient()
+        return self.t_table
+
+    def ValueRange(self, col):
+        # Performance of sqlite vs. DBF for this method:
+        #
+        # If the table has been copied to the sqlite database it's
+        # faster to use it even if there is no index on that column.
+        # Otherwise it's faster to simply loop through all rows in the
+        # DBF file. Copying the data to the sqlite database can take
+        # very long for large amounts of data
+        #
+        # Of course if the table is not a DBF file the issue could be
+        # different, although copying the data into sqlite first will
+        # likely always be slower than simply querying the non-sqlite
+        # table directly. Currently only DBFfiles and memory tables are
+        # used as the underlying non-sqlite table, though.
+        if self.t_table is not None:
+            return self.t_table.ValueRange(col)
+        else:
+            return self.table.ValueRange(col)
+
+    def UniqueValues(self, col):
+        # The performance trade-offs for this method are basically the
+        # same as for ValueRange except that currently there doesn't
+        # seem to be a way to take advantage of indexes in this case in
+        # sqlite. However, but it's still faster to query the transient
+        # table if it already exists.
+        if self.t_table is not None:
+            return self.t_table.UniqueValues(col)
+        else:
+            return self.table.UniqueValues(col)
+
+    def SimpleQuery(self, left, comparison, right):
+        if self.t_table is None:
+            self.copy_to_transient()
+        # Make sure to use the column object of the transient table. The
+        # left argument is always a column object so we can just ask the
+        # t_table for the right object.
+        if hasattr(right, "name"):
+            return self.t_table.SimpleQuery(self.t_table.Column(left.name),
+                                            comparison, 
+                                            self.t_table.Column(right.name))
+        else:
+            return self.t_table.SimpleQuery(self.t_table.Column(left.name),
+                                            comparison, right)
+
+    def Dependencies(self):
+        """Return a tuple containing the original table"""
+        return (self.table,)
+
+    def Width(self, col):
+        return self.table.Width(col)
+
+    def write_record(self, row, values):
+        """Write the values to the given row.
+
+        This is a very experimental feature which doesn't work in all
+        cases, so you better know what you're doing when calling this
+        method.
+        """
+        self.table.write_record(row, values)

Added: packages/thuban/branches/upstream/current/Thuban/Model/wellknowntext.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/wellknowntext.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/wellknowntext.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,135 @@
+# Copyright (C) 2002, 2003 Intevation GmbH <intevation at intevation.de>
+# Author: Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file GPL coming with the software for details.
+
+"""Convert Well-Known Text format to python objects
+
+Main entry point is the convert_well_known_text function which takes a
+geometry in Well-Known Text format and returns a python object with the
+geometry.
+"""
+
+__version__ = "$Revision: 1605 $"
+# $Source$
+# $Id: wellknowntext.py 1605 2003-08-19 11:00:40Z bh $
+
+import re
+
+
+_open_parens = r"[ \t]*(\([ \t]*)*"
+_close_parens = r"[ \t]*(\)[ \t]*)+"
+rx_point_list = re.compile(_open_parens + r"(?P<coords>[^\)]+)"
+                           + _close_parens + ",?")
+
+
+def parse_coordinate_lists(wkt):
+    """Return the coordinates in wkt as a list of lists of coordinate pairs.
+
+    The wkt parameter is the coordinate part of a geometry in well-known
+    text format.
+    """
+    geometry = []
+    while wkt:
+        match = rx_point_list.match(wkt)
+        if match:
+            poly = []
+            wktcoords = match.group("coords")
+            for pair in wktcoords.split(","):
+                # a pair may be a triple actually. For now we just
+                # ignore any third value
+                x, y = map(float, pair.split())[:2]
+                poly.append((x, y))
+            geometry.append(poly)
+            wkt = wkt[match.end(0):].strip()
+        else:
+            raise ValueError("Invalid well-known-text (WKT) syntax")
+    return geometry
+
+
+def parse_multipolygon(wkt):
+    """
+    Return the MULTIPOLYGON geometry wkt as a list of lists of float pairs
+    """
+    return parse_coordinate_lists(wkt)
+
+def parse_polygon(wkt):
+    """Return the POLYGON geometry in wkt as a list of float pairs"""
+    return parse_coordinate_lists(wkt)
+
+def parse_multilinestring(wkt):
+    """
+    Return the MULTILINESTRING geometry wkt as a list of lists of float pairs
+    """
+    return parse_coordinate_lists(wkt)
+
+def parse_linestring(wkt):
+    """Return the LINESTRING geometry in wkt as a list of float pairs"""
+    return parse_coordinate_lists(wkt)[0]
+
+def parse_point(wkt):
+    """Return the POINT geometry in wkt format as pair of floats"""
+    return parse_coordinate_lists(wkt)[0][0]
+
+
+# map geometry types to parser functions
+_function_map = [
+    ("MULTIPOLYGON", parse_multipolygon),
+    ("POLYGON", parse_polygon),
+    ("MULTILINESTRING", parse_multilinestring),
+    ("LINESTRING", parse_linestring),
+    ("POINT", parse_point),
+    ]
+
+def convert_well_known_text(wkt):
+    """Return the geometry given in well-known text format as python objects
+
+    The function accepts only 2D data and supports the POINT, POLYGON,
+    MULTIPOLYGON, LINESTRING and MULTILINESTRING geometries.
+
+    The structure of the return value depends on the geometry type. For
+    MULTIPOLYGON and MULTILINESTRING return a list of lists of
+    coordinate pairs. For POLYGON and LINESTRING return a list of
+    coordinate pairs. For POINT return a coordinate pair. All
+    coordinates are floats.
+
+    The string wkt may contain an SRID specification in addition to the
+    actual geometry. This SRID is ignored.
+    """
+    parts = wkt.split(";")
+    for part in parts:
+        part = part.strip()
+        if part.startswith("SRID"):
+            # ignore SRIDs
+            continue
+        else:
+            for geotype, function in _function_map:
+                if part.startswith(geotype):
+                    return function(part[len(geotype):])
+            else:
+                raise ValueError("Unsupported WKT-part %s" % repr(part[:20]))
+    else:
+        # there were no recognized geometries in the WKT string
+        raise ValueError("No recognized geometry in WKT string")
+
+def parse_wkt_thuban(wkt):
+    """Like convert_well_known_text, but return lists of lists of pairs"""
+    parts = wkt.split(";")
+    for part in parts:
+        part = part.strip()
+        if part.startswith("SRID"):
+            # ignore SRIDs
+            continue
+        else:
+            # split on "(" to separate the geometry type from the
+            # coordinate values
+            components = part.split("(", 1)
+            if len(components) > 1:
+                return parse_coordinate_lists(components[1])
+            else:
+                raise ValueError("WKT part %r doesn't contain opening"
+                                 " parenthesis" % part)
+    else:
+        # there were no recognized geometries in the WKT string
+        raise ValueError("No recognized geometry in WKT string")

Added: packages/thuban/branches/upstream/current/Thuban/Model/xmlreader.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/xmlreader.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/xmlreader.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,134 @@
+# Copyright (C) 2003, 2005 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with GRASS for details.
+
+"""
+Parser for thuban session files.
+"""
+
+__version__ = "$Revision: 2642 $"
+
+import os
+import xml.sax
+import xml.sax.handler
+from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException
+from Thuban import internal_from_unicode
+
+class XMLReader(xml.sax.handler.ContentHandler):
+
+    # Dictionary mapping element names (or (URI, element name) pairs for
+    # documents using namespaces) to method names. The methods should
+    # accept the same parameters as the startElement (or startElementNS)
+    # methods. The start_dispatcher is used by the default startElement
+    # and startElementNS methods to call a method for the open tag of an
+    # element.
+    start_dispatcher = {}
+
+    # end_dispatcher works just like start_dispatcher but it's used by
+    # endElement and endElementNS. The method whose names it maps to
+    # should accept the same parameters as endElement and endElementNS.
+    end_dispatcher = {}
+
+
+    def __init__(self):
+        self.chars = ''
+        self.__directory = ""
+        self.__dispatchers = {}
+
+    def read(self, file_or_filename):
+
+        if hasattr(file_or_filename, "read"):
+            # it's a file object
+            self.__directory = ""
+            self.__file = file_or_filename
+        else:
+            filename = file_or_filename
+            self.__directory = os.path.dirname(filename)
+            self.__file = open(filename)
+
+        parser = make_parser()
+        parser.setContentHandler(self)
+        parser.setErrorHandler(ErrorHandler())
+        parser.setFeature(xml.sax.handler.feature_namespaces, 1)
+
+        #
+        # Well, this isn't pretty, but it appears that if you
+        # use Python 2.2 without the site-package _xmlplus then
+        # the following will fail, and without them it will work.
+        # However, if you do have the site-package and you don't
+        # call these functions, the reader raises an exception
+        #
+        # The reason we set these to 0 in the first place is 
+        # because there is an unresolved issue with external
+        # entities causing an exception in the reader
+        #
+        try:
+            parser.setFeature(xml.sax.handler.feature_validation,0)
+            parser.setFeature(xml.sax.handler.feature_external_ges,0)
+            parser.setFeature(xml.sax.handler.feature_external_pes,0)
+        except SAXNotRecognizedException:
+            pass
+
+        parser.parse(self.__file)
+
+        self.close()
+
+    def close(self):
+        self.__file.close()
+        
+    def GetFilename(self):
+        if hasattr(self.__file, "name"):
+            return self.__file.name
+
+        return ""
+
+    def GetDirectory(self):
+        return self.__directory
+
+
+    def AddDispatchers(self, dict):
+        """Add the function names that should be used to process XML tags.
+
+        dict -- a dictionary whose keys are XML tag strings and whose values
+                are pairs of strings such that the first string is
+                the name of the function that should be called when the
+                XML tag opens and the second string is the name of the
+                function that should be called when the XML tag closes.
+                If a pair element is None, no function is called.
+        """
+
+        self.__dispatchers.update(dict)
+
+    def startElementNS(self, name, qname, attrs):
+        """Call the method given for name in self.start_dispatcher
+        """
+        if name[0] is None:
+            method_name = self.__dispatchers.get(name[1])
+        else:
+            # Dispatch with namespace
+            method_name = self.__dispatchers.get(name)
+        if method_name is not None and method_name[0] is not None:
+            getattr(self, method_name[0])(name, qname, attrs)
+
+    def endElementNS(self, name, qname):
+        """Call the method given for name in self.end_dispatcher
+        """
+        if name[0] is None:
+            method_name = self.__dispatchers.get(name[1])
+        else:
+            # Dispatch with namespace
+            method_name = self.__dispatchers.get(name)
+        if method_name is not None and method_name[1] is not None:
+            getattr(self, method_name[1])(name, qname)
+
+    def encode(self, str):
+        """Return the unicode object str in Thuban's internal representation
+
+        If str is None, return None
+        """
+        if str is None:
+            return None
+        return internal_from_unicode(str)

Added: packages/thuban/branches/upstream/current/Thuban/Model/xmlwriter.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/Model/xmlwriter.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/Model/xmlwriter.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,132 @@
+# Copyright (c) 2003, 2005 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Functions to save an XML file
+"""
+
+__version__ = "$Revision: 2642 $"
+
+import os
+from types import UnicodeType
+
+from Thuban import unicode_from_internal
+
+#
+# one level of indention
+#
+TAB = "    "
+
+def escape(data):
+    """Escape &, \", ', <, and > in a string of data.
+    """
+    data = data.replace("&", "&amp;")
+    data = data.replace("<", "&lt;")
+    data = data.replace(">", "&gt;")
+    data = data.replace('"', "&quot;")
+    data = data.replace("'", "&apos;")
+    return data
+
+class XMLWriter:
+    """Abstract XMLWriter.
+
+    Should be overridden to provide specific object saving functionality.
+    """
+
+    def __init__(self):
+        self.filename = None
+        pass
+
+    def write(self, file_or_filename):
+        """Write the session to a file.
+
+        The argument may be either a file object or a filename. If it's
+        a filename, the file will be opened for writing. Files of
+        shapefiles will be stored as filenames relative to the directory
+        the file is stored in (as given by os.path.dirname(filename)) if
+        they have a common parent directory other than the root
+        directory.
+
+        If the argument is a file object (which is determined by the
+        presence of a write method) all filenames will be absolute
+        filenames.
+        """
+
+        # keep track of how many levels of indentation to write
+        self.indent_level = 0 
+        # track whether an element is currently open. see open_element().
+        self.element_open = 0
+
+        if hasattr(file_or_filename, "write"):
+            # it's a file object
+            self.file = file_or_filename
+            self.dir = ""
+        else:
+            self.filename = file_or_filename
+            self.dir = os.path.dirname(self.filename)
+            self.file = open(self.filename, 'w')
+
+    def close(self):
+        assert self.indent_level == 0
+        if self.filename is not None:
+            self.file.close()
+
+    def write_header(self, doctype, system):
+        """Write the XML header"""
+        self.file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
+        self.file.write('<!DOCTYPE %s SYSTEM "%s">\n' % (doctype, system))
+
+    def open_element(self, element, attrs = {}):
+
+        #
+        # we note when an element is opened so that if two open_element()
+        # calls are made successively we can end the currently open
+        # tag and will later write a proper close tag. otherwise,
+        # if a close_element() call is made directly after an open_element()
+        # call we will close the tag with a />
+        #
+        if self.element_open == 1:
+            self.file.write(">\n")
+
+        self.element_open = 1
+
+        # Helper function to write an element open tag with attributes
+        self.file.write("%s<%s" % (TAB*self.indent_level, element))
+        self.__write_attribs(attrs)
+
+        self.indent_level += 1
+
+    def close_element(self, element):
+        self.indent_level -= 1
+        assert self.indent_level >= 0
+
+        # see open_element() for an explanation
+        if self.element_open == 1:
+            self.element_open = 0
+            self.file.write("/>\n")
+        else:
+            self.file.write("%s</%s>\n" % (TAB*self.indent_level, element))
+
+    def write_element(self, element, attrs = {}):
+        """write an element that won't need a closing tag"""
+        self.open_element(element, attrs)
+        self.close_element(element)
+
+    def __write_attribs(self, attrs):
+        for name, value in attrs.items():
+            self.file.write(' %s="%s"' % (self.encode(name), 
+                                          self.encode(value)))
+
+    def encode(self, s):
+        """Return an XML-escaped and UTF-8 encoded copy of the string s.
+
+        The parameter must be a string in Thuban's internal string
+        representation or a unicode object.
+        """
+        if not isinstance(s, unicode):
+            s = unicode_from_internal(s)
+        return escape(s).encode("utf8")

Added: packages/thuban/branches/upstream/current/Thuban/UI/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,77 @@
+# Copyright (c) 2001, 2002, 2003, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+
+_locale = None
+def install_wx_translation():
+    """Install the wx translation function in Thuban.
+
+    For more information about translations in Thuban see the comment in
+    Thuban/__init__.py
+    """
+    global _locale
+    import Thuban
+    if not Thuban.translation_function_installed():
+        # Only import wx modules when we actually can install the
+        # function so that the test suite can inhibit this
+        import wx
+        wx.Locale_AddCatalogLookupPathPrefix(Thuban._message_dir)
+        _locale = wx.Locale(wx.LANGUAGE_DEFAULT)
+        _locale.AddCatalog("thuban")
+
+        # With a unicode build of wxPython, wxGetTranslation returns a
+        # unicode object, so we have a wrapper that handles the case of
+        # not using unicode as the internal string representation of
+        # Thuban: If wxGetTranslation returns unicode and the internal
+        # string representation of Thuban is not unicode, we convert the
+        # translated string to the internal representation.  wxPython
+        # will convert such strings back to unicode if necessary,
+        # provided the internal encoding used is the one expected by
+        # wxPython, which is taken care of below.
+        def thuban_wx_translation(s):
+            t = wx.GetTranslation(s)
+            if isinstance(t, unicode) and Thuban._internal_encoding!="unicode":
+                t = t.encode(Thuban._internal_encoding, "replace")
+            return t
+
+        Thuban.install_translation_function(thuban_wx_translation)
+
+        # Reset the python locale. This makes sure that the LC_NUMERIC
+        # seen by the python interpreter and by C modules is "C" instead
+        # of the user's locale. Python code will still see the user's
+        # locale where it matters. Without this, drawing the map doesn't
+        # work for some reason
+        import locale
+        locale.setlocale(locale.LC_NUMERIC, "")
+
+        # determine the internal encoding to use.
+        # This is very tricky.  It's probably not optimal yet.
+        encoding = None
+
+        # If we have a wxPython >= 2.5.4.1, we use the
+        # GetDefaultPyEncoding function to use exactly what wxPython
+        # also uses when converting between unicode and byte-strings ...
+        if hasattr(wx, "GetDefaultPyEncoding"):
+            # AFAICT from the code this will always be a usable string,
+            # although it could be "ascii".
+            internal_encoding = wx.GetDefaultPyEncoding()
+
+        # ... otherwise we use Python's getdefaultlocale.  This is what
+        # GetDefaultPyEncoding also uses ...
+        if encoding is None:
+            encoding = locale.getdefaultlocale()[1]
+
+        # ... finally, if we haven't figured it out yet, use latin 1 for
+        # historical reasons.  Maybe ascii would be better.
+        if encoding is None:
+            encoding = "latin1"
+
+        # set the encoding
+        Thuban.set_internal_encoding(encoding)
+
+
+install_wx_translation()

Added: packages/thuban/branches/upstream/current/Thuban/UI/about.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/about.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/about.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,177 @@
+# Copyright (c) 2001-2007 by Intevation GmbH 
+# vim: set fileencoding=ISO-8859-15 :
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+# Bernhard Reiter <bernhard at intevation.de>
+# Silke Reimer <silke at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""The About Box"""
+
+__version__ = "$Revision: 2736 $"
+# $Source$
+# $Id: about.py 2736 2007-03-13 22:21:51Z bernhard $
+
+import wx
+
+from Thuban import _, internal_from_unicode, get_internal_encoding
+from Thuban.version import versions
+from Thuban.Model.resource import gdal_support_status
+
+from Thuban.UI.extensionregistry import ext_registry
+
+class About(wx.Dialog):
+
+    def __init__(self, parent):
+        wx.Dialog.__init__(self, parent, -1, _("About Thuban"),
+            style = wx.DEFAULT_DIALOG_STYLE
+                  | wx.SYSTEM_MENU
+                  | wx.MINIMIZE_BOX
+                  | wx.MAXIMIZE_BOX
+                  | wx.RESIZE_BORDER,
+            size = (400, 250))
+
+        # Note: The source code is in ASCII, so we escape some
+        # characters to get byte strings in latin1.
+        maintainers = [ 'Bernhard Reiter (2006 - current)',
+                        'Bernhard Herzog (2001 - 2005)' ]
+        lead_developer = 'Bernhard Herzog (2001 - 2005)'
+        developers = [ 'Jonathan Coles (2003, 2005)',
+                       'Frank Koormann (2002 - )',
+                       internal_from_unicode(u'Martin M\xfcller (2003)'),
+                       'Didrik Pinte (2006 - )',
+                       'Bernhard Reiter (2004 - )',
+                       'Jan-Oliver Wagner (2002 - 2005)' ]
+        translators = [ ( _('French'), 'Daniel Calvelo Aros' ),
+                        ( _('German'),
+                          internal_from_unicode(u'Bj\xf6rn Broscheit')),
+                        ( _('Hungarian'), 'Norbert Solymosi'),
+                        ( _('Italian'), 'Maurizio Napolitano'),
+                        ( _('Portuguese (Brazilian)'), 'Eduardo Patto Kanegae'),
+                        ( _('Russian'), 'Alex Shevlakov'),
+                        ( _('Spanish'), 'Daniel Calvelo Aros') ]
+        other_contributors = [ 'Jonathan Byron (2004)',
+                               'Ole Rahn (2004)',
+                               'Silke Reimer (2003, 2004)',
+                               'Martin "Joey" Schulze (2004, 2005)' ]
+        dyn_modules = [ ('wxPython', versions['wxPython']),
+                        ('Python',   versions['python']),
+                        ('PySQLite', versions['pysqlite']),
+                        ('SQLite',  versions['sqlite']),
+                        ('GDAL', versions.get('gdal', _('- not available'))),
+                        ('psycopg', versions.get('psycopg',
+                                                 _('- not available')))]
+        direct_modules = [ \
+                ('GTK',      versions.get('gtk', _('- not available'))),
+                ('proj',     versions['proj']) ]
+
+        text = 'Thuban %s\n\n' % versions['thuban-long']
+
+        text += _('Currently using:\n')
+
+        for name, version in dyn_modules:
+            text+= '\t%s %s\n' % (name, version)
+        text += '\n'
+
+        text += _('\tInternal encoding: %s\n') % get_internal_encoding()
+        text += '\n'
+
+        if gdal_support_status:
+            text += gdal_support_status + "\n\n"
+
+        text += _('Compiled for:\n')
+
+        for name, version in direct_modules:
+            text+= '\t%s %s\n' % (name, version)
+        text += '\n'
+
+        text += _('Extensions:\n')
+        if ext_registry:
+            for ext in ext_registry:
+                text += '\t%s %s\n' % (ext.name, ext.version)
+        else:
+            text += _('\tNone registered.\n')
+        text += '\n'
+
+        text += _('Maintainers:\n')
+        for name in maintainers:
+            text += '\t%s\n' % name
+        text += '\n'
+
+        text += _('Lead Developer:\n')
+        text += '\t%s\n\n' % lead_developer
+
+        text += _('Developers:\n')
+        for name in developers:
+            text += '\t%s\n' % name
+        text += '\n'
+
+        text += _('Translators:\n')
+        for lang, name in translators:
+            text += '\t%s: %s\n' % (lang, name)
+        text += '\n'
+
+        text += _('Other Contributors:\n')
+        for name in other_contributors:
+            text += '\t%s\n' % name
+        text += '\n'
+
+        text += \
+            _("Questions and comments can be sent to the following addresses:\n"
+            "\tGeneral list (public):\n\t\t<thuban-list at intevation.de>\n"
+            "\tDevelopers list (public):\n\t\t<thuban-devel at intevation.de>\n"
+            "\tThuban team at Intevation:\n\t\t<thuban at intevation.de>\n"
+            )
+
+        text += '\n\n'
+
+        text += _("Details on the registered extensions:\n\n")
+
+        if ext_registry:
+            for ext in ext_registry:
+                text += '%s %s:\n' % (ext.name, ext.version)
+                text += _('Copyright %s\n') % ext.copyright
+                text += _('Authors:\n')
+                for author in ext.authors:
+                    text+= '\t%s\n' % author
+                text += ext.desc
+                text += '\n'
+                text += 'Status: %s' % ext.status
+                text += '\n\n'
+        else:
+            text += _('\tNone registered.\n')
+
+        self.text = text
+
+        text_title = wx.StaticText(self, -1,
+            _("Thuban is a program for exploring geographic data.\n\n") +
+            "Copyright 2001-2007 Intevation GmbH.\n" +
+            _("Thuban is licensed under the GNU GPL"),
+                                  style=wx.ST_NO_AUTORESIZE|wx.ALIGN_CENTRE)
+
+        textBox = wx.TextCtrl(self, -1, text,
+            style=wx.TE_READONLY|wx.TE_MULTILINE|wx.TE_LINEWRAP)
+        w, h = (300, 150)
+        textBox.SetSizeHints(w, h)
+        textBox.SetSize((w, h))
+
+        button_close = wx.Button(self, wx.ID_CANCEL, _("Close"))
+        button_close.SetDefault()
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        sizer.Add(text_title, 0, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 10)
+        sizer.Add(textBox, 1, wx.ALL|wx.EXPAND, 10)
+        sizer.Add(button_close, 0, wx.ALL|wx.ALIGN_RIGHT, 10)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+        sizer.SetSizeHints(self)
+        self.Layout()
+
+        self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
+
+    def OnCancel(self, event):
+        self.EndModal(wx.ID_CANCEL)

Added: packages/thuban/branches/upstream/current/Thuban/UI/altpathdialog.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/altpathdialog.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/altpathdialog.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,60 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Frank Koormann <frank at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+
+"""Dialogs for alternative paths (path recovery).
+
+   AltPathFileDialog:    File dialog to specify alterative path.
+   AltPathConfirmDialog: Confirm or cancel alternative path suggestion.
+"""
+
+from Thuban import _
+
+import wx
+
+import os
+
+class AltPathFileDialog(wx.FileDialog):
+
+    def __init__(self, filename):
+        msg = _("Select an alternative data file for %s" % \
+                        os.path.basename(filename))
+
+        wx.FileDialog.__init__(self, None,
+                           msg,
+                           os.path.dirname(filename),
+                           os.path.basename(filename),
+                           _("Shapefiles (*.shp)") + "|*.shp;*.SHP|" +
+                           _("All Files (*.*)") + "|*.*",
+                           wx.OPEN)
+
+    def RunDialog(self):
+        val = self.ShowModal()
+        self.Destroy()
+        if val == wx.ID_OK:
+            return self.GetPaths()[0]
+        else:
+            return None
+
+class AltPathConfirmDialog(wx.MessageDialog):
+
+    def __init__(self, filename):
+        self.filename = filename
+        msg = _("Found the following as an alternative for %s.\n%s\n\n Please confirm with Yes or select alternative with No." % (os.path.basename(filename), filename))
+
+        wx.MessageDialog.__init__(self, None, msg, _("Alternative Path"),
+                        wx.YES_NO|wx.YES_DEFAULT|wx.ICON_INFORMATION)
+
+    def RunDialog(self):
+        val = self.ShowModal()
+        self.Destroy()
+        if val == wx.ID_YES:
+            return self.filename
+        else:
+            dlg = AltPathFileDialog(self.filename)
+            fname = dlg.RunDialog()
+            return fname

Added: packages/thuban/branches/upstream/current/Thuban/UI/application.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/application.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/application.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,383 @@
+# Copyright (C) 2001-2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Thuban's application object.
+"""
+
+__version__ = "$Revision: 2700 $"
+
+import sys, os
+import os.path
+
+import traceback
+
+import wx
+
+from Thuban.Lib.connector import Publisher
+from Thuban.Lib.fileutil import get_application_dir
+
+from Thuban import _
+from Thuban.Model.session import create_empty_session
+from Thuban.Model.save import save_session
+from Thuban.Model.load import load_session, LoadCancelled
+from Thuban.Model.messages import MAPS_CHANGED
+from Thuban.Model.layer import RasterLayer
+import Thuban.Model.resource
+
+from extensionregistry import ext_registry
+
+import view
+import tree
+import mainwindow
+import dbdialog
+import altpathdialog
+import exceptiondialog
+
+from messages import SESSION_REPLACED
+
+
+class ThubanApplication(wx.App, Publisher):
+
+    """
+    Thuban's application class.
+
+    All wxWindows programs have to have an instance of an application
+    class derived from wxApp. In Thuban the application class holds
+    references to the main window and the session.
+    """
+
+    def OnInit(self):
+        sys.excepthook = self.ShowExceptionDialog
+
+        # Initialize instance variables before trying to create any
+        # windows.  Creating windows can start an event loop if
+        # e.g. message boxes are popped up for some reason, and event
+        # handlers, especially EVT_UPDATE_UI may want to access things
+        # from the application.
+
+        # Defaults for the directories used in file dialogs
+        self.path={"data":".", "projection":".", "alt_path":""}
+
+        self.session = None
+        self.top = None
+        self.create_session()
+
+        # Create an optional splash screen and then the mainwindow
+        self.splash = self.splash_screen()
+        if self.splash is not None:
+            self.splash.Show()
+        self.read_startup_files()
+        self.init_extensions()
+        self.top = self.CreateMainWindow()
+        # The session was alredy created above and we need to get the
+        # map into the mainwindow.  maps_changed does that.
+        self.maps_changed()
+        self.SetTopWindow(self.top)
+        if self.splash is None:
+            self.ShowMainWindow()
+
+        return True
+
+    def OnExit(self):
+        """Clean up code.
+
+        Extend this in derived classes if needed.
+        """
+        self.session.Destroy()
+        self.session = None
+        Publisher.Destroy(self)
+
+    def read_startup_files(self):
+        """Read the startup files."""
+        # for now the startup file is ~/.thuban/thubanstart.py
+        dir = get_application_dir()
+        if os.path.isdir(dir):
+            sys.path.append(dir)
+            try:
+                import thubanstart
+            except ImportError:
+                tb = sys.exc_info()[2]
+                try:
+                    if tb.tb_next is not None:
+                        # The ImportError exception was raised from
+                        # inside the thubanstart module.
+                        sys.stderr.write(_("Cannot import the thubanstart"
+                                         " module\n"))
+                        traceback.print_exc(None, sys.stderr)
+                    else:
+                        # There's no thubanstart module.
+                        sys.stderr.write(_("No thubanstart module available\n"))
+                finally:
+                    # make sure we delete the traceback object,
+                    # otherwise there's be circular references involving
+                    # the current stack frame
+                    del tb
+            except:
+                sys.stderr.write(_("Cannot import the thubanstart module\n"))
+                traceback.print_exc(None, sys.stderr)
+        else:
+            # There's no .thuban directory
+            sys.stderr.write(_("No ~/.thuban directory\n"))
+
+    def init_extensions(self):
+        """Call initialization callbacks for all registered extensions."""
+        for ext in ext_registry:
+            ext.init_ext()
+
+    def splash_screen(self):
+        """Create and return a splash screen.
+
+        This method is called by OnInit to determine whether the
+        application should have a splashscreen. If the application
+        should display a splash screen override this method in a derived
+        class and have it create and return the wxSplashScreen instance.
+        The implementation of this method in the derived class should
+        also arranged for ShowMainWindow to be called.
+
+        The default implementation simply returns None so that no splash
+        screen is shown and ShowMainWindow will be called automatically.
+        """
+        return None
+
+    def ShowMainWindow(self):
+        """Show the main window
+
+        Normally this method is automatically called by OnInit to show
+        the main window. However, if the splash_screen method has
+        returned a splashscreen it is expected that the derived class
+        also arranges for ShowMainWindow to be called at the appropriate
+        time.
+        """
+        self.top.Show(True)
+
+    def CreateMainWindow(self):
+        """Create and return the main window for the application.
+
+        Override this in subclasses to instantiate the Thuban mainwindow
+        with different parameters or to use a different class for the
+        main window.
+        """
+        msg = (_("This is the wxPython-based Graphical User Interface"
+               " for exploring geographic data"))
+        return mainwindow.MainWindow(None, -1, "Thuban", self, None,
+                                     initial_message = msg,
+                                     size = (600, 400))
+
+    def Session(self):
+        """Return the application's session object"""
+        return self.session
+
+    def SetSession(self, session):
+        """Make session the new session.
+
+        Issue SESSION_REPLACED after self.session has become the new
+        session. After the session has been assigned call
+        self.subscribe_session() with the new session and
+        self.unsubscribe_session with the old one.
+        """
+        oldsession = self.session
+        self.session = session
+        self.subscribe_session(self.session)
+        self.issue(SESSION_REPLACED)
+        self.maps_changed()
+        if oldsession is not None:
+            self.unsubscribe_session(oldsession)
+            oldsession.Destroy()
+
+    def SetPath(self, group, filename):
+        """Store the application's default path for file dialogs extracted
+        from a given filename.
+        """
+        self.path[group] = os.path.dirname( filename )
+
+    def Path(self, group):
+        """Return the application's default path for file dialogs."""
+        return self.path[group]
+
+    def subscribe_session(self, session):
+        """Subscribe to some of the sessions channels.
+
+        Extend this method in derived classes if you need additional
+        channels.
+        """
+        session.Subscribe(MAPS_CHANGED, self.maps_changed)
+
+    def unsubscribe_session(self, session):
+        """Unsubscribe from the sessions channels.
+
+        Extend this method in derived classes if you subscribed to
+        additional channels in subscribe_session().
+        """
+        session.Unsubscribe(MAPS_CHANGED, self.maps_changed)
+
+    def create_session(self):
+        """Create a default session.
+
+        Override this method in derived classes to instantiate the
+        session differently or to use a different session class. Don't
+        subscribe to channels here yet. Do that in the
+        subscribe_session() method.
+        """
+        self.SetSession(create_empty_session())
+
+    def OpenSession(self, filename, db_connection_callback = None,
+                                    shapefile_callback = None):
+        """Open the session in the file named filename"""
+        # Make sure we deal with an absolute pathname. Otherwise we can
+        # get problems when saving because the saving code expects an
+        # absolute directory name
+        filename = os.path.abspath(filename)
+        if db_connection_callback is None:
+            db_connection_callback = self.run_db_param_dialog
+        if shapefile_callback is None:
+            shapefile_callback = self.run_alt_path_dialog
+        try:
+            session = load_session(filename,
+                               db_connection_callback=db_connection_callback,
+                               shapefile_callback=shapefile_callback)
+        except LoadCancelled:
+            return
+        session.SetFilename(filename)
+        session.UnsetModified()
+        self.SetSession(session)
+
+        for map in session.Maps():
+            for layer in map.Layers():
+                if isinstance(layer, RasterLayer) \
+                    and not Thuban.Model.resource.has_gdal_support():
+                    msg = _("The current session contains Image layers,\n"
+                            "but the GDAL library is not available to "
+                            "draw them.")
+                    dlg = wx.MessageDialog(None,
+                                             msg,
+                                             _("Library not available"),
+                                             wx.OK | wx.ICON_INFORMATION)
+                    print msg
+                    dlg.ShowModal()
+                    dlg.Destroy()
+                    break
+
+    def run_db_param_dialog(self, parameters, message):
+        """Implementation of the db_connection_callback for loading sessions"""
+        dlg = dbdialog.DBDialog(None, _("DB Connection Parameters"),
+                                parameters, message)
+        return dlg.RunDialog()
+
+    # run_alt_path_dialog: Raise a dialog to ask for an alternative path
+    # if the shapefile couldn't be found.
+    # TODO: 
+    #   - Store a list of already used alternative paths and return these 
+    #     iteratively (using a generator) 
+    #   - How do we interact with the user to tell him we used a different 
+    #     shapefile (location), mode "check"? The current approach with the 
+    #     file dialog is not that comfortable.
+    #
+    def run_alt_path_dialog(self, filename, mode = None, second_try = 0):
+        """Implemetation of the shapefile_callback while loading sessions.
+        
+           This implements two modes:
+           - search: Search for an alternative path. If available from a 
+             list of alrady known paths, else interactivly by file dialog.
+             Currently the "second_try" is important since else the user might
+             be caught in a loop.
+           - check: Ask the user for confirmation, if a path from list has
+             been found successful.
+
+           Returns:
+           - fname: The full path to the (shape) file.
+           - from_list: Flags if the path was taken from list or entered
+             manually.
+        """
+
+        if mode == "search":
+            if self.Path('alt_path') == "" or second_try:
+                dlg = altpathdialog.AltPathFileDialog(filename)
+                fname = dlg.RunDialog()
+                if fname is not None:
+                    self.SetPath('alt_path', fname)
+                from_list = 0
+            else:
+                fname = os.path.join(self.Path('alt_path'),
+                                     os.path.basename(filename))
+                from_list = 1
+        elif mode == "check":
+                dlg = altpathdialog.AltPathConfirmDialog(filename)
+                fname = dlg.RunDialog()
+                if fname is not None:
+                    self.SetPath('alt_path', fname)
+                from_list = 0
+        else:
+            fname = None
+            from_list = 0
+        return fname, from_list
+
+
+    def SaveSession(self):
+        save_session(self.session, self.session.filename)
+
+    def maps_changed(self, *args):
+        """Subscribed to the session's MAPS_CHANGED messages.
+
+        Set the toplevel window's map to the map in the session. This is
+        done by calling the window's SetMap method with the map as
+        argument. If the session doesn't have any maps None is used
+        instead.
+
+        Currently Thuban can only really handle at most one map in a
+        sessions so the first map in the session's list of maps as
+        returned by the Maps method is used.
+        """
+        # The mainwindow may not have been created yet, so check whether
+        # it has been created before calling any of its methods
+        if self.top is not None:
+            if self.session.HasMaps():
+                self.top.SetMap(self.session.Maps()[0])
+            else:
+                self.top.SetMap(None)
+
+    in_exception_dialog = 0 # flag: are we already inside the exception dialog?
+
+    def ShowExceptionDialog(self, exc_type, exc_value, exc_traceback):
+        """Show a message box with information about an exception.
+    
+        The parameters are the usual values describing an exception in
+        Python, the exception type, the value and the traceback.
+    
+        This method can be used as a value for the sys.excepthook.
+        """
+
+        if self.in_exception_dialog:
+            return
+        self.in_exception_dialog = 1
+        while wx.IsBusy():
+            wx.EndBusyCursor() # reset the mouse cursor
+
+        try:
+            lines = traceback.format_exception(exc_type, exc_value,
+                                            exc_traceback)
+            message = _("An unhandled exception occurred:\n%s\n"
+                        "(please report to"
+                        " http://thuban.intevation.org/bugtracker.html)"
+                        "\n\n%s") % (exc_value, "".join(lines))
+            print message
+
+            # We don't use an explicit parent here because this method might
+            # be called in circumstances where the main window doesn't exist
+            # anymore.
+            exceptiondialog.run_exception_dialog(None, message)
+
+        finally:
+            self.in_exception_dialog = 0
+            # delete the last exception info that python keeps in
+            # sys.last_* because especially last_traceback keeps
+            # indirect references to all objects bound to local
+            # variables and this might prevent some object from being
+            # collected early enough.
+            sys.last_type = sys.last_value = sys.last_traceback = None
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/baserenderer.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/baserenderer.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/baserenderer.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,601 @@
+# Copyright (c) 2001, 2002, 2003, 2004 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Jonathan Coles <jonathan at intevation.de>
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Basic rendering logic for Thuban maps
+
+The code in this module is completely independend of wx so that it can
+be tested reasonably easily and it could make it easier to write non-wx
+renderers.
+"""
+
+from __future__ import generators
+
+__version__ = "$Revision: 2718 $"
+# $Source$
+# $Id: baserenderer.py 2718 2007-01-05 23:43:49Z dpinte $
+
+import sys
+import traceback
+
+from Thuban.Model.layer import Layer, RasterLayer
+from Thuban.Model.data import SHAPETYPE_ARC, SHAPETYPE_POINT
+from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
+     ALIGN_LEFT, ALIGN_RIGHT
+
+import Thuban.Model.resource
+
+
+
+#
+#       Renderer Extensions
+#
+# The renderer extensions provide a way to render layer types defined in
+# Thuban extensions. The renderer extensions are stored as a list with
+# (layer_class, draw_function) pairs. If the renderer has to draw a
+# non-builtin layer type, i.e. a layer that is not a subclass of Layer
+# or RasterLayer, it iterates through that list, tests whether the layer
+# to be drawn is an instance of layer_class and if so calls
+# draw_function with the renderer and the layer as arguments. Since
+# drawing is done incrementally, the draw_function should return an
+# iterable. The easiest way is to simply implement the draw_function as
+# a generator and to yield in suitable places, or to return the empty
+# tuple.
+#
+# New renderer extensions should be added with add_renderer_extension().
+# If necessary the extensions list can be reset with
+# init_renderer_extensions().
+
+_renderer_extensions = []
+
+def add_renderer_extension(layer_class, function):
+    """Add a renderer extension for the layer class layer_class
+
+    When an instance of layer_class is to be drawn by the renderer the
+    renderer will call function with the renderer and the layer_class
+    instance as arguments. Since drawing is done incrementally, the
+    function should return an iterable. The easiest way is to simply
+    implement the draw_function as a generator and to yield True in
+    suitable places, or to return the empty tuple if it's not possible
+    to do the rendering incrementally.
+    """
+    _renderer_extensions.append((layer_class, function))
+
+def init_renderer_extensions():
+    """(Re)initialize the list of renderer extensions
+
+    Calling this function outside of the test suite is probably not
+    useful.
+    """
+    del _renderer_extensions[:]
+
+def proj_params_to_str(proj):
+    "Build a string suitable for GDAL describing the given projection"
+    str = ""
+    if proj is not None:
+        for p in proj.GetAllParameters():
+            str += "+" + p + " "
+    return str
+
+#
+#       Base Renderer
+#
+
+class BaseRenderer:
+
+    """Basic Renderer Infrastructure for Thuban Maps
+
+    This class can't be used directly to render because it doesn't know
+    anything about real DCs such as how to create pens or brushes. That
+    functionality has to be provided by derived classes. The reason for
+    this is that it makes the BaseRenderer completely independend of wx
+    and thus it's quite easy to write test cases for it.
+    """
+    # If true the render honors the visibility flag of the layers
+    honor_visibility = 1
+
+    # Transparent brushes and pens. Derived classes should define these
+    # as appropriate.
+    TRANSPARENT_PEN = None
+    TRANSPARENT_BRUSH = None
+
+    def __init__(self, dc, map, scale, offset, region = None,
+                 resolution = 72.0, honor_visibility = None):
+        """Inititalize the renderer.
+
+        dc -- the device context to render on.
+
+        scale, offset -- the scale factor and translation to convert
+                between projected coordinates and the DC coordinates
+
+        region -- The region to draw as a (x, y, width, height) tuple in
+                  the map's coordinate system. Default is None meaning
+                  to draw everything.
+
+        resolution -- the assumed resolution of the DC. Used to convert
+                absolute lengths like font sizes to DC coordinates. The
+                default is 72.0. If given, this parameter must be
+                provided as a keyword argument.
+
+        honor_visibility -- boolean. If true, honor the visibility flag
+                of the layers, otherwise draw all layers. If None (the
+                default), use the renderer's default. If given, this
+                parameter must be provided as a keyword argument.
+        """
+        # resolution in pixel/inch
+        self.dc = dc
+        self.map = map
+        self.scale = scale
+        self.offset = offset
+        self.region = region
+        if honor_visibility is not None:
+            self.honor_visibility = honor_visibility
+        # store the resolution in pixel/point because it's more useful
+        # later.
+        self.resolution = resolution / 72.0
+
+    def tools_for_property(self, prop):
+        """Return a suitable pen and brush for the property
+
+        This method must be implemented in derived classes. The return
+        value should be a tuple (pen, brush).
+        """
+        raise NotImplementedError
+
+    def render_map(self):
+        """Render the map onto the DC.
+
+        Both map and DC are the ones the renderer was instantiated with.
+
+        This method is just a front-end for render_map_incrementally
+        which does all rendering in one go. It also calls the dc's
+        BeginDrawing and EndDrawing methods before and after calling
+        render_map_incrementally.
+        """
+
+        self.dc.BeginDrawing()
+        try:
+            for cont in self.render_map_incrementally():
+                pass
+        finally:
+            self.dc.EndDrawing()
+
+    def render_map_incrementally(self):
+        """Render the map incrementally.
+
+        Return an iterator whose next method should be called until it
+        returns False. After returning False it will raise StopIteration
+        so that you could also use it in a for loop (implementation
+        detail: this method is implemented as a generator).
+
+        Iterate through all layers and draw them. Layers containing
+        vector data are drawn with the draw_shape_layer method, raster
+        layers are drawn with draw_raster_layer. The label layer is
+        drawn last with draw_label_layer.
+
+        During execution of this method, the map is bound to self.map so
+        that methods especially in derived classes have access to the
+        map if necessary.
+        """
+
+        for layer in self.map.Layers():
+            # if honor_visibility is true, only draw visible layers,
+            # otherwise draw all layers
+            if not self.honor_visibility or layer.Visible():
+                if isinstance(layer, Layer):
+                    for i in self.draw_shape_layer_incrementally(layer):
+                        yield True
+                elif isinstance(layer, RasterLayer):
+                    self.draw_raster_layer(layer)
+                    yield True
+                else:
+                    # look it up in the renderer extensions
+                    for cls, func in _renderer_extensions:
+                        if isinstance(layer, cls):
+                            for i in func(self, layer):
+                                yield True
+                            break
+                    else:
+                        # No renderer found. Print a message about it
+                        print >>sys.stderr, ("Drawing layer %r not supported"
+                                             % layer)
+            yield True
+
+        self.draw_label_layer(self.map.LabelLayer())
+        yield False
+
+    def draw_shape_layer_incrementally(self, layer):
+        """Draw the shape layer layer onto the map incrementally.
+
+        This method is a generator which yields True after every 500
+        shapes.
+        """
+        scale = self.scale
+        offx, offy = self.offset
+
+        map_proj = self.map.projection
+        layer_proj = layer.projection
+
+        brush = self.TRANSPARENT_BRUSH
+        pen   = self.TRANSPARENT_PEN
+
+        old_prop = None
+        old_group = None
+        lc = layer.GetClassification()
+        field = layer.GetClassificationColumn()
+        defaultGroup = lc.GetDefaultGroup()
+        table = layer.ShapeStore().Table()
+
+        if lc.GetNumGroups() == 0:
+            # There's only the default group, so we can pretend that
+            # there is no field to classifiy on which makes things
+            # faster since we don't need the attribute information at
+            # all.
+            field = None
+
+        # Determine which render function to use.
+        useraw, draw_func, draw_func_param = self.low_level_renderer(layer)
+
+        #
+        # Iterate through all shapes that have to be drawn.
+        #
+
+        # Count the shapes drawn so that we can yield every few hundred
+        # shapes
+        count = 0
+
+        # Cache the tools (pens and brushes) for the classification
+        # groups. This is a mapping from the group's ids to the a tuple
+        # (pen, brush)
+        tool_cache = {}
+
+        for shape in self.layer_shapes(layer):
+            count += 1
+            if field is None:
+                group = defaultGroup
+            else:
+                value = table.ReadValue(shape.ShapeID(), field)
+                group = lc.FindGroup(value)
+
+            if not group.IsVisible():
+                continue
+
+            try:
+                pen, brush = tool_cache[id(group)]
+            except KeyError:
+                pen, brush = tool_cache[id(group)] \
+                             = self.tools_for_property(group.GetProperties())
+
+            if useraw:
+                data = shape.RawData()
+            else:
+                data = shape.Points()
+            if draw_func == self.draw_point_shape:
+                 draw_func(draw_func_param, data, pen, brush,
+                           size = group.GetProperties().GetSize())
+            else:
+                 draw_func(draw_func_param, data, pen, brush)
+            if count % 500 == 0:
+                yield True
+
+    def layer_shapes(self, layer):
+        """Return an iterable over the shapes to be drawn from the given layer.
+
+        The default implementation simply returns all ids in the layer.
+        Override in derived classes to be more precise.
+        """
+        return layer.ShapeStore().AllShapes()
+
+    def low_level_renderer(self, layer):
+        """Return the low-level renderer for the layer for draw_shape_layer
+
+        The low level renderer to be returned by this method is a tuple
+        (useraw, func, param) where useraw is a boolean indicating
+        whether the function uses the raw shape data, func is a callable
+        object and param is passed as the first parameter to func. The
+        draw_shape_layer method will call func like this:
+
+            func(param, shapedata, pen, brush)
+
+        where shapedata is the return value of the RawData method of the
+        shape object if useraw is true or the return value of the Points
+        method if it's false. pen and brush are the pen and brush to use
+        to draw the shape on the dc.
+
+        The default implementation returns one of
+        self.draw_polygon_shape, self.draw_arc_shape or
+        self.draw_point_shape as func and layer as param. None of the
+        method use the raw shape data. Derived classes can override this
+        method to return more efficient low level renderers.
+        """
+        shapetype = layer.ShapeType()
+        if shapetype == SHAPETYPE_POINT:
+            func = self.draw_point_shape
+        elif shapetype == SHAPETYPE_ARC:
+            func = self.draw_arc_shape
+        else:
+            func = self.draw_polygon_shape
+        return False, func, layer
+
+    def make_point(self, x, y):
+        """Convert (x, y) to a point object.
+
+        Derived classes must override this method.
+        """
+        raise NotImplementedError
+
+    def projected_points(self, layer, points):
+        """Return the projected coordinates of the points taken from layer.
+
+        Transform all the points in the list of lists of coordinate
+        pairs in points.
+
+        The transformation applies the inverse of the layer's projection
+        if any, then the map's projection if any and finally applies
+        self.scale and self.offset.
+
+        The returned list has the same structure as the one returned the
+        shape's Points method.
+        """
+        proj = self.map.GetProjection()
+        if proj is not None:
+            forward = proj.Forward
+        else:
+            forward = None
+        proj = layer.GetProjection()
+        if proj is not None:
+            inverse = proj.Inverse
+        else:
+            inverse = None
+        result = []
+        scale = self.scale
+        offx, offy = self.offset
+        make_point = self.make_point
+
+        for part in points:
+            result.append([])
+            for x, y in part:
+                if inverse:
+                    x, y = inverse(x, y)
+                if forward:
+                    x, y = forward(x, y)
+                result[-1].append(make_point(x * scale + offx,
+                                             -y * scale + offy))
+        return result
+
+    def draw_polygon_shape(self, layer, points, pen, brush):
+        """Draw a polygon shape from layer with the given brush and pen
+
+        The shape is given by points argument which is a the return
+        value of the shape's Points() method. The coordinates in the
+        DC's coordinate system are determined with
+        self.projected_points.
+
+        For a description of the algorithm look in wxproj.cpp.
+        """
+        points = self.projected_points(layer, points)
+
+        if brush is not self.TRANSPARENT_BRUSH:
+            polygon = []
+            for part in points:
+                polygon.extend(part)
+
+            # missing back vertices for correct filling.
+            insert_index = len(polygon)
+            for part in points[:-1]:
+                polygon.insert(insert_index, part[0])
+
+            self.dc.SetBrush(brush)
+            self.dc.SetPen(self.TRANSPARENT_PEN)
+            self.dc.DrawPolygon(polygon)
+
+        if pen is not self.TRANSPARENT_PEN:
+            # At last draw the boundarys of the simple polygons
+            self.dc.SetBrush(self.TRANSPARENT_BRUSH)
+            self.dc.SetPen(pen)
+            for part in points:
+                self.dc.DrawLines(part)
+
+    def draw_arc_shape(self, layer, points, pen, brush):
+        """Draw an arc shape from layer with the given brush and pen
+
+        The shape is given by points argument which is a the return
+        value of the shape's Points() method. The coordinates in the
+        DC's coordinate system are determined with
+        self.projected_points.
+        """
+        points = self.projected_points(layer, points)
+        self.dc.SetBrush(brush)
+        self.dc.SetPen(pen)
+        for part in points:
+            self.dc.DrawLines(part)
+
+    def draw_point_shape(self, layer, points, pen, brush, size = 5):
+        """Draw a point shape from layer with the given brush and pen
+
+        The shape is given by points argument which is a the return
+        value of the shape's Points() method. The coordinates in the
+        DC's coordinate system are determined with
+        self.projected_points.
+
+        The point is drawn as a circle centered on the point.
+        """
+        points = self.projected_points(layer, points)
+        if not points:
+            return
+
+        radius = int(round(self.resolution * size))
+        self.dc.SetBrush(brush)
+        self.dc.SetPen(pen)
+        for part in points:
+            for p in part:
+                self.dc.DrawEllipse(p.x - radius, p.y - radius,
+                                    2 * radius, 2 * radius)
+
+    def draw_raster_layer(self, layer):
+        """Draw the raster layer
+
+        This implementation uses self.projected_raster_layer() to project 
+        and scale the data as required by the layer's and map's projections 
+        and the scale and offset of the renderer and then hands the transformed 
+        data to self.draw_raster_data() which has to be implemented in
+        derived classes.
+        """
+        offx, offy = self.offset
+        width, height = self.dc.GetSizeTuple()
+
+        in_proj  = proj_params_to_str(layer.GetProjection())
+        out_proj = proj_params_to_str(self.map.GetProjection())
+
+        # True  -- warp the image to the size of the whole screen
+        # False -- only use the bound box of the layer (currently inaccurate)
+        if True:
+        #if False: 
+            pmin = [0,height]
+            pmax = [width, 0]
+        else:
+            bb = layer.LatLongBoundingBox()
+            bb = [[[bb[0], bb[1]], [bb[2], bb[3]],],]
+            pmin, pmax = self.projected_points(layer, bb)[0]
+
+        #print bb
+        #print pmin, pmax
+
+        fmin = [max(0, min(pmin[0], pmax[0])) - offx,
+                offy - min(height, max(pmin[1], pmax[1]))]
+
+        fmax = [min(width, max(pmin[0], pmax[0])) - offx,
+                offy - max(0, min(pmin[1], pmax[1]))]
+
+        xmin = fmin[0]/self.scale
+        ymin = fmin[1]/self.scale
+        xmax = fmax[0]/self.scale
+        ymax = fmax[1]/self.scale
+
+        width  = int(min(width,  round(fmax[0] - fmin[0] + 1)))
+        height = int(min(height, round(fmax[1] - fmin[1] + 1)))
+
+        options = 0
+        options = options | layer.MaskType()
+
+        img_data = self.projected_raster_layer(layer, in_proj, out_proj,
+                    (xmin,ymin,xmax,ymax), [0,0], (width, height), options)
+
+        if img_data is not None:
+            data = (width, height, img_data)
+            self.draw_raster_data(fmin[0]+offx, offy-fmax[1],
+                                  data, format="RAW", opacity=layer.Opacity())
+            data = None
+
+    def projected_raster_layer(self, layer, srcProj, dstProj, extents,
+                               resolution, dimensions, options):
+        """Return the projected raster image associated with the layer.
+
+        The returned value will be a tuple of the form
+
+            (image_data, mask_data, alpha_data)
+
+        suitable for the data parameter to draw_raster_data.
+
+        The return value may be None if raster projections are not supported.
+
+        srcProj     --  a string describing the source projection
+        dstProj     --  a string describing the destination projection
+        extents     --  a tuple of the region to project in map coordinates
+        resolution  --  (currently not used, defaults to [0,0])
+        dimensions  --  a tuple (width, height) for the output image
+        options     --  bit-wise options to pass to the renderer
+
+        the currently supported values for options are
+
+            OPTS_MASK        = 1  -- generate a mask
+            OPTS_ALPHA       = 2  -- generate an alpha channel
+            OPTS_INVERT_MASK = 4  -- invert the values in the mask 
+                                     (if generated)
+
+        This method has to be implemented by derived classes.
+        """
+
+        raise NotImplementedError
+
+    def draw_raster_data(self, x, y, data, format="BMP", opacity=1.0):
+        """Draw a raster image held in data onto the DC with the top
+        left corner at (x,y)
+
+        The raster image data is a tuple of the form
+            (width, height, (image_data, mask_data, alpha_data))
+        
+        holding the image width, height, image data, mask data, and alpha data.
+        mask_data may be None if a mask should not be used. alpha_data may
+        also be None. If both are not None mask overrides alpha. If 
+        format is 'RAW' the data will be RGB values and the mask
+        will be in XMB format. Otherwise, both kinds 
+        of data are assumed to be in the format specified in format.
+
+        The format parameter is a string with the name of the format.
+        The following format names should be used:
+
+          'RAW'  -- an array of RGB values (len=3*width*height)
+          'PNG'  -- Portable Network Graphic (transparency supported)
+          'BMP'  -- Windows Bitmap
+          'TIFF' -- Tagged Image File Format
+          'GIF'  -- GIF Image
+          'JPEG' -- JPEG Image
+
+        The default format is 'BMP'.
+
+        This method has to be implemented by derived classes. The
+        implementation in the derived class should try to support at
+        least the formats specified above and may support more.
+        """
+        raise NotImplementedError
+
+    def label_font(self):
+        """Return the font object for the label layer"""
+        raise NotImplementedError
+
+    def draw_label_layer(self, layer):
+        """Draw the label layer
+
+        All labels are draw in the font returned by self.label_font().
+        """
+        scale = self.scale
+        offx, offy = self.offset
+
+        self.dc.SetFont(self.label_font())
+
+        map_proj = self.map.projection
+        if map_proj is not None:
+            forward = map_proj.Forward
+        else:
+            forward = None
+
+        for label in layer.Labels():
+            x = label.x
+            y = label.y
+            text = label.text
+            if forward:
+                x, y = forward(x, y)
+            x = int(round(x * scale + offx))
+            y = int(round(-y * scale + offy))
+            width, height = self.dc.GetTextExtent(text.decode('iso-8859-1'))
+            if label.halign == ALIGN_LEFT:
+                # nothing to be done
+                pass
+            elif label.halign == ALIGN_RIGHT:
+                x = x - width
+            elif label.halign == ALIGN_CENTER:
+                x = x - width/2
+            if label.valign == ALIGN_TOP:
+                # nothing to be done
+                pass
+            elif label.valign == ALIGN_BOTTOM:
+                y = y - height
+            elif label.valign == ALIGN_CENTER:
+                y = y - height/2
+            self.dc.DrawText(text.decode('iso-8859-1'), x, y)

Added: packages/thuban/branches/upstream/current/Thuban/UI/classgen.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/classgen.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/classgen.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1003 @@
+# Copyright (c) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""The Classification Generator Dialog"""
+
+__version__ = "$Revision: 2709 $"
+# $Source$
+# $Id: classgen.py 2709 2006-10-03 09:34:51Z dpinte $
+
+
+import sys
+
+import wx
+
+from Thuban import _
+
+from Thuban.Model.classification import ClassGroupProperties
+
+from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
+     FIELDTYPE_STRING
+
+from Thuban.Model.layer import SHAPETYPE_ARC
+from Thuban.Model.range import Range
+from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
+
+import classifier, resource
+
+from Thuban.Model.classgen import \
+    generate_uniform_distribution, generate_singletons, generate_quantiles, \
+    CustomRamp, grey_ramp, red_ramp, green_ramp, blue_ramp, green_to_red_ramp, \
+    HotToColdRamp, FixedRamp
+
+
+USEALL_BMP  = "group_use_all"
+USE_BMP     = "group_use"
+USENOT_BMP  = "group_use_not"
+USENONE_BMP = "group_use_none"
+
+GENCOMBOSTR_UNIFORM = _("Uniform Distribution")
+GENCOMBOSTR_UNIQUE = _("Unique Values")
+GENCOMBOSTR_QUANTILES = _("Quantiles from Table")
+
+PROPCOMBOSTR_CUSTOM     = _("Custom Ramp")
+PROPCOMBOSTR_GREY       = _("Grey Ramp")
+PROPCOMBOSTR_RED        = _("Red Ramp")
+PROPCOMBOSTR_GREEN      = _("Green Ramp")
+PROPCOMBOSTR_BLUE       = _("Blue Ramp")
+PROPCOMBOSTR_GREEN2RED  = _("Green-to-Red Ramp")
+PROPCOMBOSTR_HOT2COLD   = _("Hot-to-Cold Ramp")
+
+ID_CLASSGEN_GENCOMBO = 4007
+ID_CLASSGEN_PROPCOMBO = 4008
+
+ID_BORDER_COLOR = 4009
+ID_BORDER_COLOR_CHANGE = 4010
+
+class ClassGenDialog(wx.Dialog):
+
+    def __init__(self, parent, layer, fieldName):
+        """Inialize the class generating dialog.
+
+        parent -- this must be an instance of the Classifier class
+        """
+
+        wx.Dialog.__init__(self, parent, -1, _("Generate Classification"),
+                          style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
+
+        self.parent = parent
+        self.layer = layer
+        self.clazz = None
+
+        col = layer.ShapeStore().Table().Column(fieldName)
+        self.type = col.type
+
+        self.fieldName = fieldName
+        self.fieldType = self.type
+
+        self.curGenPanel = None
+
+        self.genpanels = []
+
+        #############
+        # we need to create genButton first because when we create the
+        # panels they will call AllowGenerate() which uses genButton.
+        #
+        self.genButton = wx.Button(self, wx.ID_OK, _("Generate"))
+        self.cancelButton = wx.Button(self, wx.ID_CANCEL, _("Close"))
+        self.genButton.SetDefault()
+
+        self.genChoice = wx.Choice(self, ID_CLASSGEN_GENCOMBO)
+
+        self.genpanels.append((GENCOMBOSTR_UNIQUE, GenUniquePanel))
+        if self.type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
+            self.genpanels.append((GENCOMBOSTR_UNIFORM, GenUniformPanel))
+            self.genpanels.append((GENCOMBOSTR_QUANTILES, GenQuantilesPanel))
+
+        for name, clazz in self.genpanels:
+            self.genChoice.Append(name, [clazz, None])
+
+        self.genChoice.SetSelection(0)
+
+        for i in range(self.genChoice.GetCount()):
+            clazz, obj = self.genChoice.GetClientData(i)
+
+            if obj is None:
+                obj = clazz(self, self.layer, self.fieldName, self.fieldType)
+                obj.Hide()
+                self.genChoice.SetClientData(i, [clazz, obj])
+
+
+        #############
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        sizer.Add(wx.StaticText(self, -1, _("Field: %s") % fieldName),
+                  0, wx.ALL, 4)
+        sizer.Add(wx.StaticText(
+            self, -1,
+            _("Data Type: %s") % classifier.Classifier.type2string[self.type]),
+            0, wx.ALL, 4)
+
+        psizer = wx.BoxSizer(wx.HORIZONTAL)
+        psizer.Add(wx.StaticText(self, -1, _("Generate:")),
+            0, wx.ALIGN_CENTER_VERTICAL, 0)
+        psizer.Add(self.genChoice, 1, wx.ALL | wx.GROW, 4)
+
+        sizer.Add(psizer, 0, wx.ALL | wx.GROW, 4)
+
+        self.sizer_genPanel = wx.BoxSizer(wx.VERTICAL)
+        sizer.Add(self.sizer_genPanel, 1, wx.GROW | wx.ALL, 4)
+
+        psizer = wx.BoxSizer(wx.HORIZONTAL)
+        psizer.Add(wx.StaticText(self, -1, _("Color Scheme:")),
+            0, wx.ALIGN_CENTER_VERTICAL, 0)
+
+        # Properties (Ramp) ComboBox
+        self.propCombo = wx.Choice(self, ID_CLASSGEN_PROPCOMBO)
+
+        self.propPanel = None
+        custom_ramp_panel = CustomRampPanel(self, layer.ShapeType())
+
+        self.propCombo.Append(PROPCOMBOSTR_GREY,  grey_ramp)
+        self.propCombo.Append(PROPCOMBOSTR_RED,   red_ramp)
+        self.propCombo.Append(PROPCOMBOSTR_GREEN, green_ramp)
+        self.propCombo.Append(PROPCOMBOSTR_BLUE,  blue_ramp)
+        self.propCombo.Append(PROPCOMBOSTR_GREEN2RED, green_to_red_ramp)
+        self.propCombo.Append(PROPCOMBOSTR_HOT2COLD,  HotToColdRamp())
+        self.propCombo.Append(PROPCOMBOSTR_CUSTOM, custom_ramp_panel)
+
+        self.propCombo.SetSelection(0)
+
+        psizer.Add(self.propCombo, 1, wx.ALL | wx.GROW, 4)
+        sizer.Add(psizer, 0, wx.ALL | wx.GROW, 4)
+
+        if layer.ShapeType() != SHAPETYPE_ARC:
+            psizer = wx.BoxSizer(wx.HORIZONTAL)
+            self.fix_border_check = wx.CheckBox(self, -1, _("Fix Border Color"))
+            psizer.Add(self.fix_border_check, 0, wx.ALL | wx.GROW, 4)
+            self.border_color = classifier.ClassGroupPropertiesCtrl(
+                self, ID_BORDER_COLOR,
+                ClassGroupProperties(), SHAPETYPE_ARC,
+                style=wx.SIMPLE_BORDER, size=(40, 20))
+            psizer.Add(self.border_color, 0, wx.ALL | wx.GROW, 4)
+            psizer.Add(wx.Button(self, ID_BORDER_COLOR_CHANGE, _("Change")),
+                    0, wx.ALL, 4)
+            sizer.Add(psizer, 0, wx.ALL | wx.GROW, 4)
+            self.Bind(wx.EVT_BUTTON, self.OnBorderColorChange, id=ID_BORDER_COLOR_CHANGE)
+        else:
+            self.border_color = None
+
+        sizer.Add(custom_ramp_panel, 1, wx.GROW | wx.ALL, 4)
+        sizer.Show(custom_ramp_panel, False)
+
+        # Finally place the main buttons
+        buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
+        buttonSizer.Add(self.genButton, 0, wx.RIGHT|wx.EXPAND, 10)
+        buttonSizer.Add(self.cancelButton, 0, wx.RIGHT|wx.EXPAND, 10)
+        sizer.Add(buttonSizer, 0, wx.ALIGN_RIGHT|wx.BOTTOM|wx.TOP, 10)
+
+        self.SetSizer(sizer)
+        self.SetAutoLayout(True)
+        sizer.SetSizeHints(self)
+
+        self.topBox = sizer
+
+        self.__DoOnGenTypeSelect()
+
+        self.Bind(wx.EVT_CHOICE, self._OnGenTypeSelect, id=ID_CLASSGEN_GENCOMBO)
+        self.Bind(wx.EVT_CHOICE, self._OnPropTypeSelect, id=ID_CLASSGEN_PROPCOMBO)
+        self.Bind(wx.EVT_BUTTON, self.OnOK, self.genButton)
+        self.Bind(wx.EVT_BUTTON, self.OnCancel, self.cancelButton)
+
+        self.__DoOnGenTypeSelect()
+
+        self.genChoice.SetFocus()
+
+    def GetClassification(self):
+        return self.clazz
+
+    def AllowGenerate(self, on):
+        pass #self.genButton.Enable(on)
+
+    def OnOK(self, event):
+        """This is really the generate button, but we want to override
+        the wxDialog class.
+        """
+
+        index = self.genChoice.GetSelection()
+
+        assert index != -1, "button should be disabled!"
+
+        genSel = self.genChoice.GetString(index)
+        clazz, genPanel = self.genChoice.GetClientData(index)
+
+        propPanel = self.propPanel
+
+        if genSel in (GENCOMBOSTR_UNIFORM,          \
+                      GENCOMBOSTR_UNIQUE,           \
+                      GENCOMBOSTR_QUANTILES):
+
+            numGroups = genPanel.GetNumGroups()
+
+            index = self.propCombo.GetSelection()
+
+            propSel = self.propCombo.GetString(index)
+            propPanel = self.propCombo.GetClientData(index)
+
+            ramp = propPanel.GetRamp()
+            if self.border_color and self.fix_border_check.IsChecked():
+                props = self.border_color.GetProperties()
+                ramp = FixedRamp(ramp,
+                    (props.GetLineColor(), props.GetLineWidth(), None))
+
+            if genSel == GENCOMBOSTR_UNIFORM:
+
+                min = genPanel.GetMin()
+                max = genPanel.GetMax()
+
+                if min is not None \
+                    and max is not None \
+                    and numGroups is not None:
+
+                    self.clazz = generate_uniform_distribution(
+                                min, max, numGroups, ramp,
+                                self.type == FIELDTYPE_INT)
+
+                    self.parent._SetClassification(self.clazz)
+
+            elif genSel == GENCOMBOSTR_UNIQUE:
+
+                list = genPanel.GetValueList()
+
+                if len(list) > 0:
+                    self.clazz = generate_singletons(list, ramp)
+                    self.parent._SetClassification(self.clazz)
+
+            elif genSel == GENCOMBOSTR_QUANTILES:
+
+                _range = genPanel.GetRange()
+                _list = genPanel.GetList()
+                _list.sort()
+
+                delta = 1 / float(numGroups)
+                percents = [delta * i for i in range(1, numGroups + 1)]
+                adjusted, self.clazz = \
+                    generate_quantiles(_list, percents, ramp, _range)
+
+                if adjusted:
+                    dlg = wx.MessageDialog(self,
+                        _("Based on the data from the table and the input\n"
+                     "values, the exact quantiles could not be generated.\n\n"
+                          "Accept a close estimate?"),
+                        _("Problem with Quantiles"),
+
+                        wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
+                    if dlg.ShowModal() == wx.ID_YES:
+                        self.parent._SetClassification(self.clazz)
+                else:
+                    self.parent._SetClassification(self.clazz)
+
+    def OnCancel(self, event):
+        self.Close()
+
+    def OnBorderColorChange(self, event):
+        self.border_color.DoEdit()
+
+    def _OnGenTypeSelect(self, event):
+        self.__DoOnGenTypeSelect()
+        return
+
+        combo = event.GetEventObject()
+
+        selIndex = combo.GetSelection()
+
+        if self.genPanel is not None:
+            self.topBox.Show(self.genPanel, False)
+
+        self.genPanel = combo.GetClientData(selIndex)
+        if self.genPanel is not None:
+            self.topBox.Show(self.genPanel, True)
+
+        self.topBox.SetSizeHints(self)
+        self.topBox.Layout()
+
+    def _OnPropTypeSelect(self, event):
+        combo = event.GetEventObject()
+
+        selIndex = combo.GetSelection()
+        sel = combo.GetString(selIndex)
+
+        if isinstance(self.propPanel, wx.Panel):
+            self.topBox.Show(self.propPanel, False)
+
+        self.propPanel = combo.GetClientData(selIndex)
+
+        if isinstance(self.propPanel, wx.Panel):
+            self.topBox.Show(self.propPanel, True)
+
+        self.topBox.SetSizeHints(self)
+        self.topBox.Layout()
+
+    def __DoOnGenTypeSelect(self):
+        choice = self.genChoice
+
+        sel = choice.GetSelection()
+        if sel == -1: return
+
+        clazz, obj = choice.GetClientData(sel)
+
+        if self.curGenPanel is not None:
+            self.curGenPanel.Hide()
+            self.sizer_genPanel.Remove(self.curGenPanel)
+
+        self.curGenPanel = obj
+        self.curGenPanel.Show()
+
+        self.sizer_genPanel.Add(self.curGenPanel, 1,
+            wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 3)
+        self.sizer_genPanel.Layout()
+        self.Layout()
+        self.topBox.SetSizeHints(self)
+
+ID_UNIFORM_MIN = 4001
+ID_UNIFORM_MAX = 4002
+ID_UNIFORM_NGROUPS = 4003
+ID_UNIFORM_STEP = 4004
+ID_UNIFORM_RETRIEVE = 4005
+
+class GenUniformPanel(wx.Panel):
+
+    def __init__(self, parent, layer, fieldName, fieldType):
+        wx.Panel.__init__(self, parent, -1)
+
+        self.parent = parent
+        self.layer = layer
+        self.fieldName = fieldName
+        self.fieldType = fieldType
+
+        topSizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, ""),
+                                    wx.VERTICAL)
+
+        #############
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+        sizer.Add(wx.StaticText(self, -1, _("Min:")), 0, wx.ALL, 4)
+        self.minCtrl = wx.TextCtrl(self, ID_UNIFORM_MIN, style=wx.TE_RIGHT)
+        sizer.Add(self.minCtrl, 1, wx.ALL, 4)
+        self.Bind(wx.EVT_TEXT, self._OnRangeChanged, id=ID_UNIFORM_MIN)
+
+        sizer.Add(wx.StaticText(self, -1, _("Max:")), 0, wx.ALL, 4)
+        self.maxCtrl = wx.TextCtrl(self, ID_UNIFORM_MAX, style=wx.TE_RIGHT)
+        sizer.Add(self.maxCtrl, 1, wx.ALL, 4)
+        self.Bind(wx.EVT_TEXT, self._OnRangeChanged, id=ID_UNIFORM_MAX)
+
+        sizer.Add(wx.Button(self, ID_UNIFORM_RETRIEVE, _("Retrieve From Table")),
+            0, wx.ALL, 4)
+        self.Bind(wx.EVT_BUTTON, self._OnRetrieve, id=ID_UNIFORM_RETRIEVE)
+
+        topSizer.Add(sizer, 1, wx.GROW, 0)
+
+        #############
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+        sizer.Add(wx.StaticText(self, -1, _("Number of Groups:")), 0, wx.ALL, 4)
+        self.numGroupsCtrl = wx.SpinCtrl(self, ID_UNIFORM_NGROUPS,
+                                        style=wx.TE_RIGHT)
+        self.Bind(wx.EVT_TEXT, self._OnNumGroupsChanged, id=ID_UNIFORM_NGROUPS)
+        self.Bind(wx.EVT_SPINCTRL, self._OnNumGroupsChanged, id=ID_UNIFORM_NGROUPS)
+        sizer.Add(self.numGroupsCtrl, 1, wx.ALL, 4)
+
+        sizer.Add(wx.StaticText(self, -1, _("Stepping:")), 0, wx.ALL, 4)
+        self.stepCtrl = wx.TextCtrl(self, ID_UNIFORM_STEP, style=wx.TE_RIGHT)
+        self.Bind(wx.EVT_TEXT, self._OnSteppingChanged, id=ID_UNIFORM_STEP)
+        sizer.Add(self.stepCtrl , 1, wx.ALL, 4)
+
+        topSizer.Add(sizer, 1, wx.GROW, 0)
+
+        #############
+
+        self.SetSizer(topSizer)
+        self.SetAutoLayout(True)
+        topSizer.SetSizeHints(self)
+
+        self.numGroupsChanging = False
+        self.steppingChanging = False
+
+        self.numGroupsCtrl.SetRange(1, sys.maxint)
+
+        self.numGroupsCtrl.SetValue(1)
+        self.stepCtrl.SetValue("1")
+        self.maxCtrl.SetValue("0")
+        self.minCtrl.SetValue("0")
+        self.minCtrl.SetFocus()
+
+    def GetNumGroups(self):
+        value = self.numGroupsCtrl.GetValue()
+        return self.__GetValidatedTypeEntry(self.numGroupsCtrl,
+                                            value,
+                                            FIELDTYPE_INT,
+                                            None)
+
+    def GetStepping(self):
+        step = self.stepCtrl.GetValue()
+        return self.__GetValidatedTypeEntry(self.stepCtrl,
+                                            step,
+                                            self.fieldType,
+                                            0)
+
+    def GetMin(self):
+        min = self.minCtrl.GetValue()
+        max = self.maxCtrl.GetValue()
+        return self.__GetValidatedTypeEntry(self.minCtrl,
+                                            min,
+                                            self.fieldType,
+                                            max)
+
+    def GetMax(self):
+        min = self.minCtrl.GetValue()
+        max = self.maxCtrl.GetValue()
+        return self.__GetValidatedTypeEntry(self.maxCtrl,
+                                            max,
+                                            self.fieldType,
+                                            min)
+
+    def _OnRangeChanged(self, event):
+
+        hasFocus = wx.Window_FindFocus() == event.GetEventObject()
+        min = self.GetMin()
+        max = self.GetMax()
+
+        on = min is not None \
+            and max is not None
+
+        self.numGroupsCtrl.Enable(on)
+        self.stepCtrl.Enable(on)
+
+        ngroups = self.GetNumGroups()
+
+        if ngroups is not None  \
+            and min is not None \
+            and max is not None \
+            and ngroups != 0:
+
+            #self.stepCtrl.SetValue(str((max - min) / ngroups))
+            self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
+            #self.numGroupsCtrl.SetValue(ngroups)
+
+            self.parent.AllowGenerate(self.GetStepping() is not None)
+        else:
+            self.parent.AllowGenerate(False)
+
+
+        if hasFocus:
+            event.GetEventObject().SetFocus()
+
+    def _OnNumGroupsChanged(self, event):
+        if self.steppingChanging:
+            self.steppingChanging = False
+            return
+
+
+        obj = event.GetEventObject()
+        ngroups = self.GetNumGroups()
+        min = self.GetMin()
+        max = self.GetMax()
+
+        if ngroups is not None  \
+            and min is not None \
+            and max is not None \
+            and ngroups != 0:
+
+            #
+            # changing the value in the stepCtrl sends an event
+            # that the control is changing, at which point
+            # we try to update the numGroupsCtrl. This causes
+            # an infinite recursion. This flag and the one
+            # called steppingChanging tries to prevent the recursion.
+            #
+            self.numGroupsChanging = True
+
+            self.stepCtrl.SetValue(str(self.__CalcStepping(min, max, ngroups)))
+
+            self.parent.AllowGenerate(self.GetStepping() is not None)
+        else:
+            self.parent.AllowGenerate(False)
+
+
+    def _OnSteppingChanged(self, event):
+        if self.numGroupsChanging:
+            self.numGroupsChanging = False
+            return
+
+        step = self.GetStepping()
+        min = self.GetMin()
+        max = self.GetMax()
+
+        if step is not None  \
+            and min is not None \
+            and max is not None \
+            and step != 0:
+
+            #
+            # see note in _OnNumGroupsChanged
+            #
+            self.steppingChanging = True
+            self.numGroupsCtrl.SetValue(self.__CalcNumGroups(min, max, step))
+
+            self.parent.AllowGenerate(self.GetNumGroups() is not None)
+        else:
+            self.parent.AllowGenerate(False)
+
+    def _OnRetrieve(self, event):
+        table = self.layer.ShapeStore().Table()
+        if table is not None:
+            ThubanBeginBusyCursor()
+            try:
+                min, max = table.ValueRange(self.fieldName)
+                self.minCtrl.SetValue(str(min))
+                self.maxCtrl.SetValue(str(max))
+            finally:
+                ThubanEndBusyCursor()
+
+    def __GetValidatedTypeEntry(self, win, value, type, badValue = None):
+
+        if type == FIELDTYPE_INT:
+            func = int
+        elif type == FIELDTYPE_DOUBLE:
+            func = float
+        elif type == FIELDTYPE_STRING:
+            func = str
+        else:
+            assert False, "Unsupported FIELDTYPE"
+            pass
+
+        if self.__ValidateEntry(win, value, func, badValue):
+            return func(value)
+
+        return None
+
+    def __ValidateEntry(self, win, value, test, badValue = None):
+
+        valid = value != ""
+
+        try:
+            if valid:
+                value = test(value)
+
+                if badValue is not None:
+                    valid = value != test(badValue)
+        except ValueError:
+            valid = False
+
+        if valid:
+            win.SetForegroundColour(wx.BLACK)
+        else:
+            win.SetForegroundColour(wx.RED)
+
+        win.Refresh()
+
+        return valid
+
+    def __CalcStepping(self, min, max, ngroups):
+        if self.fieldType == FIELDTYPE_INT:
+            step = int((max - min + 1) / float(ngroups))
+        else:
+            step = (max - min) / float(ngroups)
+
+        return step
+
+    def __CalcNumGroups(self, min, max, step):
+        n = int((max - min) / step)
+        if n == 0:
+            n = 1
+
+        if self.fieldType == FIELDTYPE_INT and step == 1:
+            n += 1
+
+        return n
+
+
+ID_UNIQUE_RETRIEVE = 4001
+ID_UNIQUE_USEALL = 4002
+ID_UNIQUE_USE = 4003
+ID_UNIQUE_DONTUSE = 4004
+ID_UNIQUE_USENONE = 4005
+ID_UNIQUE_SORTAVAIL = 4006
+ID_UNIQUE_SORTUSE = 4007
+ID_UNIQUE_REVAVAIL = 4008
+ID_UNIQUE_REVUSE = 4009
+
+class GenUniquePanel(wx.Panel):
+
+    def __init__(self, parent, layer, fieldName, fieldType):
+        wx.Panel.__init__(self, parent, -1)
+
+        self.parent = parent
+        self.layer = layer
+        self.fieldName = fieldName
+        self.fieldType = fieldType
+
+        topSizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, ""),
+                                    wx.VERTICAL)
+
+
+        #bsizer = wxBoxSizer(wxVERTICAL)
+        topSizer.Add(wx.Button(self, ID_UNIQUE_RETRIEVE,
+                            _("Retrieve From Table")),
+                   0, wx.ALL | wx.ALIGN_RIGHT, 4)
+
+        self.Bind(wx.EVT_BUTTON, self._OnRetrieve, id=ID_UNIQUE_RETRIEVE)
+
+        #topSizer.Add(bsizer, 0, wx.ALL, 4)
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+        self.dataList = []
+
+        psizer = wx.BoxSizer(wx.VERTICAL)
+        self.list_avail = wx.ListCtrl(self, -1,
+                        style=wx.LC_REPORT | wx.LC_SINGLE_SEL)
+        self.list_avail.InsertColumn(0, _("Available"))
+        self.list_avail_data = []
+        psizer.Add(self.list_avail, 1, wx.GROW, 0)
+
+        bsizer = wx.BoxSizer(wx.HORIZONTAL)
+        bsizer.Add(wx.Button(self, ID_UNIQUE_SORTAVAIL, _("Sort")))
+        self.Bind(wx.EVT_BUTTON, self._OnSortList, id=ID_UNIQUE_SORTAVAIL)
+
+        bsizer.Add(wx.Button(self, ID_UNIQUE_REVAVAIL, _("Reverse")))
+        self.Bind(wx.EVT_BUTTON, self._OnReverseList, id=ID_UNIQUE_REVAVAIL)
+
+        psizer.Add(bsizer, 0, wx.GROW, 0)
+        sizer.Add(psizer, 1, wx.GROW, 0)
+
+
+        bsizer = wx.BoxSizer(wx.VERTICAL)
+
+        bmp = resource.GetBitmapResource(USEALL_BMP, wx.BITMAP_TYPE_XPM)
+        bsizer.Add(wx.BitmapButton(self, ID_UNIQUE_USEALL, bmp),
+                   0, wx.GROW | wx.ALL, 4)
+        bmp = resource.GetBitmapResource(USE_BMP, wx.BITMAP_TYPE_XPM)
+        bsizer.Add(wx.BitmapButton(self, ID_UNIQUE_USE, bmp),
+                   0, wx.GROW | wx.ALL, 4)
+        bmp = resource.GetBitmapResource(USENOT_BMP, wx.BITMAP_TYPE_XPM)
+        bsizer.Add(wx.BitmapButton(self, ID_UNIQUE_DONTUSE, bmp),
+                   0, wx.GROW | wx.ALL, 4)
+        bmp = resource.GetBitmapResource(USENONE_BMP, wx.BITMAP_TYPE_XPM)
+        bsizer.Add(wx.BitmapButton(self, ID_UNIQUE_USENONE, bmp),
+                   0, wx.GROW | wx.ALL, 4)
+
+        self.Bind(wx.EVT_BUTTON, self._OnUseAll, id=ID_UNIQUE_USEALL)
+        self.Bind(wx.EVT_BUTTON, self._OnUse, id=ID_UNIQUE_USE)
+        self.Bind(wx.EVT_BUTTON, self._OnDontUse, id=ID_UNIQUE_DONTUSE)
+        self.Bind(wx.EVT_BUTTON, self._OnUseNone, id=ID_UNIQUE_USENONE)
+
+        sizer.Add(bsizer, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
+
+        psizer = wx.BoxSizer(wx.VERTICAL)
+        self.list_use = wx.ListCtrl(self, -1,
+                        style=wx.LC_REPORT | wx.LC_SINGLE_SEL)
+        self.list_use.InsertColumn(0, _("Use"))
+        self.list_use_data = []
+        psizer.Add(self.list_use, 1, wx.GROW, 0)
+
+        bsizer = wx.BoxSizer(wx.HORIZONTAL)
+        bsizer.Add(wx.Button(self, ID_UNIQUE_SORTUSE, _("Sort")))
+        self.Bind(wx.EVT_BUTTON, self._OnSortList, id=ID_UNIQUE_SORTUSE)
+
+        bsizer.Add(wx.Button(self, ID_UNIQUE_REVUSE, _("Reverse")))
+        self.Bind(wx.EVT_BUTTON, self._OnReverseList, id=ID_UNIQUE_REVUSE)
+
+        psizer.Add(bsizer, 0, wx.GROW, 0)
+
+        sizer.Add(psizer, 1, wx.GROW, 0)
+
+
+        topSizer.Add(sizer, 1, wx.GROW, 0)
+
+        self.SetSizer(topSizer)
+        self.SetAutoLayout(True)
+        topSizer.SetSizeHints(self)
+
+        width, height = self.list_avail.GetSizeTuple()
+        self.list_avail.SetColumnWidth(0,width)
+        width, height = self.list_use.GetSizeTuple()
+        self.list_use.SetColumnWidth(0,width)
+
+        self.parent.AllowGenerate(False)
+
+    def GetNumGroups(self):
+        return self.list_use.GetItemCount()
+
+    def GetValueList(self):
+        list = []
+        for i in range(self.list_use.GetItemCount()):
+            list.append(self.dataList[self.list_use.GetItemData(i)])
+        return list
+
+    def _OnSortList(self, event):
+        id = event.GetId()
+
+        if id == ID_UNIQUE_SORTUSE:
+            list = self.list_use
+        else:
+            list = self.list_avail
+
+        list.SortItems(lambda i1, i2: cmp(self.dataList[i1],
+                                          self.dataList[i2]))
+
+    def _OnReverseList(self, event):
+        id = event.GetId()
+
+        if id == ID_UNIQUE_REVUSE:
+            list = self.list_use
+        else:
+            list = self.list_avail
+
+        #
+        # always returning 1 reverses the list
+        #
+        list.SortItems(lambda i1, i2: 1)
+
+    def _OnRetrieve(self, event):
+        self.list_use.DeleteAllItems()
+        self.list_use_data = []
+        self.list_avail.DeleteAllItems()
+        self.list_avail_data = []
+
+        ThubanBeginBusyCursor()
+        try:
+            list = self.layer.ShapeStore().Table().UniqueValues(self.fieldName)
+            index = 0
+            for v in list:
+                self.dataList.append(v)
+                i = self.list_avail.InsertStringItem(index, str(v))
+                self.list_avail.SetItemData(index, i)
+
+                self.list_avail_data.append(v)
+                index += 1
+        finally:
+            ThubanEndBusyCursor()
+
+    def _OnUseAll(self, event):
+        for i in range(self.list_avail.GetItemCount()):
+            self.__MoveListItem(0, self.list_avail, self.list_use)
+
+    def _OnUse(self, event):
+        self.__MoveSelectedItems(self.list_avail, self.list_use)
+
+    def _OnDontUse(self, event):
+        self.__MoveSelectedItems(self.list_use, self.list_avail)
+
+    def _OnUseNone(self, event):
+
+        for i in range(self.list_use.GetItemCount()):
+            self.__MoveListItem(0, self.list_use, self.list_avail)
+
+    def __MoveSelectedItems(self, list_src, list_dest):
+        while True:
+            index = list_src.GetNextItem(-1,
+                                         wx.LIST_NEXT_ALL,
+                                         wx.LIST_STATE_SELECTED)
+
+            if index == -1:
+                break
+
+            self.__MoveListItem(index, list_src, list_dest)
+
+
+    def __MoveListItem(self, index, list_src, list_dest):
+
+        item = list_src.GetItem(index)
+
+        x = list_dest.InsertStringItem(
+                list_dest.GetItemCount(),
+                str(self.dataList[item.GetData()]))
+
+        list_dest.SetItemData(x, item.GetData())
+
+        list_src.DeleteItem(index)
+
+#   def _OnListSize(self, event):
+#       list = event.GetEventObject()
+
+#       list.SetColumnWidth(0, event.GetSize().GetWidth())
+#       
+
+ID_QUANTILES_RANGE = 4001
+ID_QUANTILES_RETRIEVE = 4002
+
+class GenQuantilesPanel(wx.Panel):
+
+    def __init__(self, parent, layer, fieldName, fieldType):
+        wx.Panel.__init__(self, parent, -1)
+
+        self.parent = parent
+        self.layer = layer
+        self.fieldName = fieldName
+        self.fieldType = fieldType
+
+        topBox = wx.StaticBoxSizer(wx.StaticBox(self, -1, ""),
+                                    wx.VERTICAL)
+
+        self.text_range = wx.TextCtrl(self, ID_QUANTILES_RANGE, "")
+        self.button_retrieve = wx.Button(self, ID_QUANTILES_RETRIEVE,
+                                        _("Retrieve from Table"))
+
+        self.spin_numClasses = wx.SpinCtrl(self, -1, style=wx.TE_RIGHT)
+        self.spin_numClasses.SetRange(2, sys.maxint)
+        self.spin_numClasses.SetValue(2)
+
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        sizer.Add(wx.StaticText(self, -1, _("Apply to Range")), 0, wx.ALL, 4)
+        sizer.Add(self.text_range, 1, wx.ALL, 4)
+        sizer.Add(self.button_retrieve, 0, wx.ALL, 4)
+
+        topBox.Add(sizer, 0, wx.EXPAND, 0)
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        sizer.Add(wx.StaticText(self, -1, _("Number of Classes:")), 0, wx.ALL, 4)
+        sizer.Add(self.spin_numClasses, 1, wx.ALL, 4)
+
+        topBox.Add(sizer, 0, wx.EXPAND, 0)
+
+        self.SetSizer(topBox)
+        self.SetAutoLayout(True)
+        topBox.Fit(self)
+        topBox.SetSizeHints(self)
+
+        self.Bind(wx.EVT_TEXT, self.OnRangeText, id=ID_QUANTILES_RANGE)
+        self.Bind(wx.EVT_BUTTON, self.OnRetrieve, id=ID_QUANTILES_RETRIEVE)
+
+        self.__range = None
+
+    def GetNumGroups(self):
+        return self.spin_numClasses.GetValue()
+
+    def GetRange(self):
+        assert self.__range is not None
+
+        return self.__range
+
+    def GetList(self):
+        _list = []
+        table = self.layer.ShapeStore().Table()
+        if table is not None:
+            ThubanBeginBusyCursor()
+            try:
+                #
+                # FIXME: Replace with a call to table when the method
+                # has been written to get all the values
+                #
+                for i in range(table.NumRows()):
+                    _list.append(table.ReadValue(i, self.fieldName,
+                                                 row_is_ordinal = True))
+            finally:
+                ThubanEndBusyCursor()
+
+        return _list
+
+    def OnRangeText(self, event):
+
+        try:
+            self.__range = Range(self.text_range.GetValue())
+        except ValueError:
+            self.__range = None
+
+        if self.__range is not None:
+            self.text_range.SetForegroundColour(wx.BLACK)
+        else:
+            self.text_range.SetForegroundColour(wx.RED)
+
+    def OnRetrieve(self, event):
+        table = self.layer.ShapeStore().Table()
+        if table is not None:
+            ThubanBeginBusyCursor()
+            try:
+                min, max = table.ValueRange(self.fieldName)
+                self.text_range.SetValue("[" + str(min) + ";" + str(max) + "]")
+                # This is a workaround, which will result in OnRangeText
+                # being called twice on some platforms. 
+                # Testing showed this is needed with current wx 2.4. versions 
+                # on MacOSX to guarantee that it is called at all.
+                self.OnRangeText(None)
+            finally:
+                ThubanEndBusyCursor()
+
+ID_CUSTOMRAMP_COPYSTART = 4001
+ID_CUSTOMRAMP_COPYEND = 4002
+ID_CUSTOMRAMP_EDITSTART = 4003
+ID_CUSTOMRAMP_EDITEND = 4004
+ID_CUSTOMRAMP_SPROP = 4005
+ID_CUSTOMRAMP_EPROP = 4006
+
+class CustomRampPanel(wx.Panel):
+
+    def __init__(self, parent, shapeType):
+        wx.Panel.__init__(self, parent, -1)
+
+        topSizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, ""), wx.HORIZONTAL)
+
+        bsizer = wx.BoxSizer(wx.VERTICAL)
+        bsizer.Add(wx.StaticText(self, -1, _("Start:")), 0, wx.ALL | wx.CENTER, 4)
+        self.startPropCtrl = classifier.ClassGroupPropertiesCtrl(
+            self, ID_CUSTOMRAMP_SPROP,
+            ClassGroupProperties(), shapeType,
+            style=wx.SIMPLE_BORDER, size=(40, 20))
+        bsizer.Add(self.startPropCtrl, 1, wx.GROW | wx.ALL | wx.CENTER, 4)
+        bsizer.Add(wx.Button(self, ID_CUSTOMRAMP_EDITSTART, _("Change")),
+                   0, wx.GROW | wx.ALL | wx.CENTER, 4)
+
+        topSizer.Add(bsizer,
+                   1, wx.ALL \
+                      | wx.SHAPED \
+                      | wx.ALIGN_CENTER_HORIZONTAL \
+                      | wx.ALIGN_CENTER_VERTICAL, \
+                   4)
+
+        bmp = resource.GetBitmapResource(USE_BMP, wx.BITMAP_TYPE_XPM)
+        bsizer = wx.BoxSizer(wx.VERTICAL)
+        bsizer.Add(wx.BitmapButton(self, ID_CUSTOMRAMP_COPYSTART, bmp),
+                   0, wx.GROW | wx.ALL, 4)
+        bmp = resource.GetBitmapResource(USENOT_BMP, wx.BITMAP_TYPE_XPM)
+        bsizer.Add(wx.BitmapButton(self, ID_CUSTOMRAMP_COPYEND, bmp),
+                   0, wx.GROW | wx.ALL, 4)
+
+        topSizer.Add(bsizer,
+                   0, wx.ALL \
+                      | wx.ALIGN_CENTER_HORIZONTAL \
+                      | wx.ALIGN_CENTER_VERTICAL,
+                   4)
+
+        bsizer = wx.BoxSizer(wx.VERTICAL)
+        bsizer.Add(wx.StaticText(self, -1, _("End:")), 0, wx.ALL | wx.CENTER, 4)
+        self.endPropCtrl = classifier.ClassGroupPropertiesCtrl(
+            self, ID_CUSTOMRAMP_EPROP,
+            ClassGroupProperties(), shapeType,
+            style=wx.SIMPLE_BORDER, size=(40, 20))
+        bsizer.Add(self.endPropCtrl, 1, wx.GROW | wx.ALL | wx.CENTER, 4)
+        bsizer.Add(wx.Button(self, ID_CUSTOMRAMP_EDITEND, _("Change")),
+                   0, wx.GROW | wx.ALL | wx.CENTER, 4)
+
+        topSizer.Add(bsizer,
+                   1, wx.ALL \
+                      | wx.SHAPED \
+                      | wx.ALIGN_RIGHT \
+                      | wx.ALIGN_CENTER_HORIZONTAL \
+                      | wx.ALIGN_CENTER_VERTICAL,
+                   4)
+
+        self.Bind(wx.EVT_BUTTON, self._OnCopyStart, id=ID_CUSTOMRAMP_COPYSTART)
+        self.Bind(wx.EVT_BUTTON, self._OnCopyEnd, id=ID_CUSTOMRAMP_COPYEND)
+        self.Bind(wx.EVT_BUTTON, self._OnEditStart, id=ID_CUSTOMRAMP_EDITSTART)
+        self.Bind(wx.EVT_BUTTON, self._OnEditEnd, id=ID_CUSTOMRAMP_EDITEND)
+
+        self.SetSizer(topSizer)
+        self.SetAutoLayout(True)
+        topSizer.SetSizeHints(self)
+
+    def GetRamp(self):
+        return CustomRamp(self.startPropCtrl.GetProperties(),
+                          self.endPropCtrl.GetProperties())
+
+    def _OnCopyStart(self, event):
+        self.endPropCtrl.SetProperties(self.startPropCtrl.GetProperties())
+
+    def _OnCopyEnd(self, event):
+        self.startPropCtrl.SetProperties(self.endPropCtrl.GetProperties())
+
+    def _OnEditStart(self, event):
+        self.startPropCtrl.DoEdit()
+
+    def _OnEditEnd(self, event):
+        self.endPropCtrl.DoEdit()
+
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/classifier.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/classifier.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/classifier.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1550 @@
+# Copyright (c) 2003-2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2003-2004)
+# Martin Schulze <joey at infodrom.org> (2004)
+# Frank Koormann <frank at intevation.de> (2003, 2006)
+# Bernhard Herzog <bh at intevation.de> (2003)
+# Jonathan Coles <jonathan at intevation.de> (2003)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Dialog for classifying how layers are displayed"""
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: classifier.py 2700 2006-09-18 14:27:02Z dpinte $
+
+import copy
+import re
+
+from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
+     FIELDTYPE_STRING
+
+import wx
+from wx import grid
+
+from Thuban import _
+from Thuban.UI.common import Color2wxColour, wxColour2Color
+
+from Thuban.Model.messages import MAP_LAYERS_REMOVED, LAYER_SHAPESTORE_REPLACED
+from Thuban.Model.range import Range
+from Thuban.Model.classification import \
+    Classification, ClassGroupDefault, \
+    ClassGroupSingleton, ClassGroupPattern, ClassGroupRange, ClassGroupMap, \
+    ClassGroupProperties
+
+from Thuban.Model.color import Transparent
+
+from Thuban.Model.layer import Layer
+from Thuban.Model.data import SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT
+
+from Thuban.UI.classgen import ClassGenDialog
+from Thuban.UI.colordialog import ColorDialog
+
+from Thuban.UI.layerproperties import LayerProperties
+from messages import MAP_REPLACED
+
+
+# table columns
+COL_VISIBLE = 0
+COL_SYMBOL  = 1
+COL_VALUE   = 2
+COL_LABEL   = 3
+NUM_COLS    = 4
+
+# indices into the client data lists in Classifier.fields
+FIELD_CLASS = 0
+FIELD_TYPE = 1
+FIELD_NAME = 2
+
+#
+# this is a silly work around to ensure that the table that is
+# passed into SetTable is the same that is returned by GetTable
+#
+import weakref
+class ClassGrid(grid.Grid):
+
+
+    def __init__(self, parent, classifier):
+        """Constructor.
+
+        parent -- the parent window
+
+        clazz -- the working classification that this grid should
+                 use for display. 
+        """
+        grid.Grid.__init__(self, parent, -1, style = 0)
+
+        self.classifier = classifier
+
+        self.currentSelection = []
+
+        self.Bind(grid.EVT_GRID_CELL_LEFT_DCLICK, self._OnCellDClick)
+        self.Bind(grid.EVT_GRID_RANGE_SELECT, self._OnSelectedRange)
+        self.Bind(grid.EVT_GRID_SELECT_CELL, self._OnSelectedCell)
+        self.Bind(grid.EVT_GRID_COL_SIZE, self._OnCellResize)
+        self.Bind(grid.EVT_GRID_ROW_SIZE, self._OnCellResize)
+        self.Bind(grid.EVT_GRID_LABEL_RIGHT_CLICK, self._OnLabelRightClicked)
+
+
+    #def GetCellAttr(self, row, col):
+        #print "GetCellAttr ", row, col
+        #Grid.GetCellAttr(self, row, col)
+
+    def CreateTable(self, clazz, fieldType, shapeType, group = None):
+
+        assert isinstance(clazz, Classification)
+
+        table = self.GetTable()
+        if table is None:
+            w = self.GetDefaultColSize() * NUM_COLS \
+                + self.GetDefaultRowLabelSize()
+            h = self.GetDefaultRowSize() * 4 \
+                + self.GetDefaultColLabelSize()
+
+            self.SetDimensions(-1, -1, w, h)
+            self.SetSizeHints(w, h, -1, -1)
+            table = ClassTable(self)
+            self.SetTable(table, True)
+
+
+        self.SetSelectionMode(grid.Grid.wxGridSelectRows)
+        self.ClearSelection()
+
+        table.Reset(clazz, fieldType, shapeType, group)
+
+    def GetCurrentSelection(self):
+        """Return the currently highlighted rows as an increasing list
+           of row numbers."""
+        sel = copy.copy(self.currentSelection)
+        sel.sort()
+        return sel
+
+    def GetSelectedRows(self):
+        return self.GetCurrentSelection()
+
+    #def SetCellRenderer(self, row, col, renderer):
+        #raise ValueError(_("Must not allow setting of renderer in ClassGrid!"))
+
+    #
+    # [Set|Get]Table is taken from http://wiki.wxpython.org
+    # they are needed as a work around to ensure that the table
+    # that is passed to SetTable is the one that is returned 
+    # by GetTable.
+    #
+    def SetTable(self, object, *attributes): 
+        self.tableRef = weakref.ref(object) 
+        return grid.Grid.SetTable(self, object, *attributes) 
+
+    def GetTable(self): 
+        try:
+            return self.tableRef() 
+        except:
+            return None
+
+    def DeleteSelectedRows(self):
+        """Deletes all highlighted rows.
+
+        If only one row is highlighted then after it is deleted the
+        row that was below the deleted row is highlighted."""
+
+        sel = self.GetCurrentSelection()
+
+        # nothing to do
+        if len(sel) == 0: return
+
+        # if only one thing is selected check if it is the default
+        # data row, because we can't remove that
+        if len(sel) == 1:
+            #group = self.GetTable().GetValueAsCustom(sel[0], COL_SYMBOL, None)
+            group = self.GetTable().GetClassGroup(sel[0])
+            if isinstance(group, ClassGroupDefault):
+                wx.MessageDialog(self,
+                                _("The Default group cannot be removed."),
+                                style = wx.OK | wx.ICON_EXCLAMATION).ShowModal()
+                return
+
+
+        self.ClearSelection()
+
+        # we need to remove things from the bottom up so we don't
+        # change the indexes of rows that will be deleted next
+        sel.reverse()
+
+        #
+        # actually remove the rows
+        #
+        table = self.GetTable()
+        for row in sel:
+            table.DeleteRows(row)
+
+        #
+        # if there was only one row selected highlight the row
+        # that was directly below it, or move up one if the
+        # deleted row was the last row.
+        #
+        if len(sel) == 1:
+            r = sel[0]
+            if r > self.GetNumberRows() - 1:
+                r = self.GetNumberRows() - 1
+            self.SelectRow(r)
+
+
+    def SelectGroup(self, group, makeVisible = True):
+        if group is None: return
+
+        assert isinstance(group, ClassGroup)
+
+        table = self.GetTable()
+
+        assert table is not None
+
+        for i in range(table.GetNumberRows()):
+            g = table.GetClassGroup(i)
+            if g is group:
+                self.SelectRow(i)
+                if makeVisible:
+                    self.MakeCellVisible(i, 0)
+                break
+
+#
+# XXX: This isn't working, and there is no way to deselect rows wxPython!
+#
+#   def DeselectRow(self, row):
+#       self.ProcessEvent(
+#           GridRangeSelectEvent(-1, 
+#                                  wxEVT_GRID_RANGE_SELECT,
+#                                  self,
+#                                  (row, row), (row, row),
+#                                  sel = False))
+
+    def _OnCellDClick(self, event):
+        """Handle a double click on a cell."""
+
+        r = event.GetRow()
+        c = event.GetCol()
+
+        if c == COL_SYMBOL:
+            self.classifier.EditSymbol(r)
+        else:
+            event.Skip()
+
+    #
+    # _OnSelectedRange() and _OnSelectedCell() were borrowed
+    # from http://wiki.wxpython.org to keep track of which
+    # cells are currently highlighted
+    #
+    def _OnSelectedRange(self, event):
+        """Internal update to the selection tracking list""" 
+        if event.Selecting():
+            for index in range( event.GetTopRow(), event.GetBottomRow()+1):
+                if index not in self.currentSelection:
+                    self.currentSelection.append( index )
+        else:
+            for index in range( event.GetTopRow(), event.GetBottomRow()+1):
+                while index in self.currentSelection:
+                    self.currentSelection.remove( index )
+        #self.ConfigureForSelection() 
+
+        event.Skip()
+
+    def _OnSelectedCell( self, event ):
+        """Internal update to the selection tracking list""" 
+        self.currentSelection = [ event.GetRow() ]
+        #self.ConfigureForSelection() 
+        event.Skip()
+
+    def _OnCellResize(self, event):
+        self.FitInside()
+        event.Skip()
+
+    def _OnLabelRightClicked(self, event):
+        """Process right click on label, raise popup for row labels."""
+        row, col = event.GetRow(), event.GetCol()
+        if col == -1:
+            self.labelPopup(event, row)
+
+    def labelPopup(self, event, row):
+        """Raise grid label popup."""
+        # check if row label is Pattern or Singleton
+        label = self.GetRowLabelValue(row)
+        if (label == _("Pattern") or label == _("Singleton")):
+            xe,ye = event.GetPosition()
+            x=self.GetRowSize(row)/2
+            menu = wx.Menu()
+            patternID = wx.NewId()
+            singletonID = wx.NewId()
+
+            def _SetSingleton(event, self=self, row=row):
+                table = self.GetTable()
+                group = table.clazz.GetGroup(row - 1)
+                if not isinstance(group, ClassGroupSingleton):
+                    ngroup = ClassGroupSingleton(
+                                group.GetPattern(),
+                                group.GetProperties(),
+                                group.GetLabel()
+                                )
+                    table.SetClassGroup(row, ngroup)
+
+            def _SetPattern(event, self=self, row=row):
+                table = self.GetTable()
+                group = table.clazz.GetGroup(row - 1)
+                if not isinstance(group, ClassGroupPattern):
+                    try:
+                        re.compile(group.GetValue())
+                    except:
+                        pass
+                    else:
+                        ngroup = ClassGroupPattern(
+                                group.GetValue(),
+                                group.GetProperties(),
+                                group.GetLabel()
+                                )
+                        table.SetClassGroup(row, ngroup)
+
+            menu.Append(singletonID, _("Singleton"))
+            self.Bind(wx.EVT_MENU, _SetSingleton, id=singletonID)
+            if self.GetTable().fieldType == FIELDTYPE_STRING:
+                menu.Append(patternID, _("Pattern"))
+                self.Bind(wx.EVT_MENU, _SetPattern, id=patternID)
+            self.PopupMenu(menu, wx.Point(x,ye))
+            menu.Destroy()
+
+class ClassTable(grid.PyGridTableBase):
+    """Represents the underlying data structure for the grid."""
+
+    __col_labels = [_("Visible"), _("Symbol"), _("Value"), _("Label")]
+
+
+    def __init__(self, view = None):
+        """Constructor.
+
+        shapeType -- the type of shape that the layer uses
+
+        view -- a Grid object that uses this class for its table
+        """
+
+        grid.PyGridTableBase.__init__(self)
+
+        assert len(ClassTable.__col_labels) == NUM_COLS
+
+        self.clazz = None
+        self.__colAttr = {}
+
+        self.SetView(view)
+
+    def Reset(self, clazz, fieldType, shapeType, group = None):
+        """Reset the table with the given data.
+
+        This is necessary because wxWindows does not allow a grid's
+        table to change once it has been intially set and so we
+        need a way of modifying the data.
+
+        clazz -- the working classification that this table should
+                 use for display. This may be different from the
+                 classification in the layer.
+
+        shapeType -- the type of shape that the layer uses
+        """
+
+        assert isinstance(clazz, Classification)
+
+        self.GetView().BeginBatch()
+
+        self.fieldType = fieldType
+        self.shapeType = shapeType
+
+        self.SetClassification(clazz, group)
+        self.__Modified(-1)
+
+        self.__colAttr = {}
+
+        attr = grid.GridCellAttr()
+        attr.SetEditor(grid.GridCellBoolEditor())
+        attr.SetRenderer(grid.GridCellBoolRenderer())
+        attr.SetAlignment(wx.ALIGN_CENTER, wx.ALIGN_CENTER)
+        self.__colAttr[COL_VISIBLE] = attr
+
+        attr = grid.GridCellAttr()
+        attr.SetRenderer(ClassRenderer(self.shapeType))
+        attr.SetReadOnly()
+        self.__colAttr[COL_SYMBOL] = attr
+
+        self.GetView().EndBatch()
+        self.GetView().FitInside()
+
+    def GetClassification(self):
+        """Return the current classification."""
+        return self.clazz
+
+    def SetClassification(self, clazz, group = None):
+        """Fill in the table with the given classification.
+        Select the given group if group is not None.
+        """
+
+        self.GetView().BeginBatch()
+
+        old_len = self.GetNumberRows()
+
+        row = -1
+        self.clazz = clazz
+
+        self.__NotifyRowChanges(old_len, self.GetNumberRows())
+
+        #
+        # XXX: this is dead code at the moment
+        #
+        if row > -1:
+            self.GetView().ClearSelection()
+            self.GetView().SelectRow(row)
+            self.GetView().MakeCellVisible(row, 0)
+
+        self.__Modified()
+
+        self.GetView().EndBatch()
+        self.GetView().FitInside()
+
+    def __NotifyRowChanges(self, curRows, newRows):
+        """Make sure table updates correctly if the number of 
+        rows changes.
+        """
+        #
+        # silly message processing for updates to the number of
+        # rows and columns
+        #
+        if newRows > curRows:
+            msg = grid.GridTableMessage(self,
+                        grid.GRIDTABLE_NOTIFY_ROWS_APPENDED,
+                        newRows - curRows)    # how many
+            self.GetView().ProcessTableMessage(msg)
+            self.GetView().FitInside()
+        elif newRows < curRows:
+            msg = grid.GridTableMessage(self,
+                        grid.GRIDTABLE_NOTIFY_ROWS_DELETED,
+                        curRows,              # position
+                        curRows - newRows)    # how many
+            self.GetView().ProcessTableMessage(msg)
+            self.GetView().FitInside()
+
+    def __SetRow(self, row, group):
+        """Set a row's data to that of the group.
+
+        The table is considered modified after this operation.
+
+        row -- if row is < 0 'group' is inserted at the top of the table
+               if row is >= GetNumberRows() or None 'group' is append to 
+                    the end of the table.
+               otherwise 'group' replaces row 'row'
+        """
+
+        # either append or replace
+        if row is None or row >= self.GetNumberRows():
+            self.clazz.AppendGroup(group)
+        elif row < 0:
+            self.clazz.InsertGroup(0, group)
+        else:
+            if row == 0:
+                self.clazz.SetDefaultGroup(group)
+            else:
+                self.clazz.ReplaceGroup(row - 1, group)
+
+        self.__Modified()
+
+    def GetColLabelValue(self, col):
+        """Return the label for the given column."""
+        return self.__col_labels[col]
+
+    def GetRowLabelValue(self, row):
+        """Return the label for the given row."""
+
+        if row == 0:
+            return _("Default")
+        else:
+            group = self.clazz.GetGroup(row - 1)
+            if isinstance(group, ClassGroupDefault):   return _("Default")
+            if isinstance(group, ClassGroupSingleton): return _("Singleton")
+            if isinstance(group, ClassGroupPattern):   return _("Pattern")
+            if isinstance(group, ClassGroupRange):     return _("Range")
+            if isinstance(group, ClassGroupMap):       return _("Map")
+
+        assert False # shouldn't get here
+        return ""
+
+    def GetNumberRows(self):
+        """Return the number of rows."""
+        if self.clazz is None:
+            return 0
+
+        return self.clazz.GetNumGroups() + 1 # +1 for default group
+
+    def GetNumberCols(self):
+        """Return the number of columns."""
+        return NUM_COLS
+
+    def IsEmptyCell(self, row, col):
+        """Determine if a cell is empty. This is always false."""
+        return False
+
+    def GetValue(self, row, col):
+        """Return the object that is used to represent the given
+           cell coordinates. This may not be a string."""
+        return self.GetValueAsCustom(row, col, None)
+
+    def SetValue(self, row, col, value):
+        """Assign 'value' to the cell specified by 'row' and 'col'.
+
+        The table is considered modified after this operation.
+        """
+
+        self.SetValueAsCustom(row, col, None, value)
+
+    def GetValueAsCustom(self, row, col, typeName):
+        """Return the object that is used to represent the given
+           cell coordinates. This may not be a string.
+
+        typeName -- unused, but needed to overload wxPyGridTableBase
+        """
+
+        if row == 0:
+            group = self.clazz.GetDefaultGroup()
+        else:
+            group = self.clazz.GetGroup(row - 1)
+
+
+        if col == COL_VISIBLE:
+            return group.IsVisible()
+
+        if col == COL_SYMBOL:
+            return group.GetProperties()
+
+        if col == COL_LABEL:
+            return group.GetLabel()
+
+        # col must be COL_VALUE
+        assert col == COL_VALUE
+
+        if isinstance(group, ClassGroupDefault):
+            return _("DEFAULT")
+        elif isinstance(group, ClassGroupSingleton):
+            return group.GetValue()
+        elif isinstance(group, ClassGroupPattern):
+            return group.GetPattern()
+        elif isinstance(group, ClassGroupRange):
+            return group.GetRange()
+
+        assert False # shouldn't get here
+        return None
+
+    def __ParseInput(self, value):
+        """Try to determine what kind of input value is 
+           (string, number, or range)
+
+        Returns a tuple (type, data) where type is 0 if data is
+        a singleton value, 1 if is a range or 2 if it is a pattern.
+        """
+
+        type = self.fieldType
+
+        if type == FIELDTYPE_STRING:
+            # Approach: if we can compile the value as an expression, 
+            # make it a pattern, else a singleton.
+            # This is quite crude, however I don't have a better idea:
+            # How to distinct the singleton "Thuban" from the pattern "Thuban"?
+            try:
+                re.compile(value)
+            except:
+                return (0, value)
+            else:
+                return (2, value)
+        elif type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
+            if type == FIELDTYPE_INT:
+                # the float call allows the user to enter 1.0 for 1
+                conv = lambda p: int(float(p))
+            else:
+                conv = float
+
+            #
+            # first try to take the input as a single number
+            # if there's an exception try to break it into
+            # a range. if there is an exception here, let it 
+            # pass up to the calling function.
+            #
+            try:
+                return (0, conv(value))
+            except ValueError:
+                return (1, Range(value))
+
+        assert False  # shouldn't get here
+        return (0,None)
+
+    def SetValueAsCustom(self, row, col, typeName, value):
+        """Set the cell specified by 'row' and 'col' to 'value'.
+
+        If column represents the value column, the input is parsed
+        to determine if a string, number, or range was entered.
+        A new ClassGroup may be created if the type of data changes.
+
+        The table is considered modified after this operation.
+
+        typeName -- unused, but needed to overload wxPyGridTableBase
+        """
+
+        assert 0 <= col < self.GetNumberCols()
+        assert 0 <= row < self.GetNumberRows()
+
+        if row == 0:
+            group = self.clazz.GetDefaultGroup()
+        else:
+            group = self.clazz.GetGroup(row - 1)
+
+        mod = True # assume the data will change
+
+        if col == COL_VISIBLE:
+            group.SetVisible(value)
+        elif col == COL_SYMBOL:
+            group.SetProperties(value)
+        elif col == COL_LABEL:
+            group.SetLabel(value)
+        elif col == COL_VALUE:
+            if isinstance(group, ClassGroupDefault):
+                # not allowed to modify the default value 
+                pass
+            elif isinstance(group, ClassGroupMap):
+                # something special
+                pass
+            else: # SINGLETON, RANGE
+                try:
+                    dataInfo = self.__ParseInput(value)
+                except ValueError:
+                    # bad input, ignore the request
+                    mod = False
+                else:
+
+                    changed = False
+                    ngroup = group
+                    props = group.GetProperties()
+
+                    #
+                    # try to update the values, which may include
+                    # changing the underlying group type if the
+                    # group was a singleton and a range was entered
+                    #
+                    if dataInfo[0] == 0:
+                        if not isinstance(group, ClassGroupSingleton):
+                            ngroup = ClassGroupSingleton(props = props)
+                            changed = True
+                        ngroup.SetValue(dataInfo[1])
+                    elif dataInfo[0] == 1:
+                        if not isinstance(group, ClassGroupRange):
+                            ngroup = ClassGroupRange(props = props)
+                            changed = True
+                        ngroup.SetRange(dataInfo[1])
+                    elif dataInfo[0] == 2:
+                        if not isinstance(group, ClassGroupPattern):
+                            ngroup = ClassGroupPattern(props = props)
+                            changed = True
+                        ngroup.SetPattern(dataInfo[1])
+                    else:
+                        assert False
+                        pass
+
+                    if changed:
+                        ngroup.SetLabel(group.GetLabel())
+                        self.SetClassGroup(row, ngroup)
+        else:
+            assert False # shouldn't be here
+            pass
+
+        if mod:
+            self.__Modified()
+            self.GetView().Refresh()
+
+    def GetAttr(self, row, col, someExtraParameter):
+        """Returns the cell attributes"""
+
+        return self.__colAttr.get(col, grid.GridCellAttr()).Clone()
+
+    def GetClassGroup(self, row):
+        """Return the ClassGroup object representing row 'row'."""
+
+        #return self.GetValueAsCustom(row, COL_SYMBOL, None)
+        if row == 0:
+            return self.clazz.GetDefaultGroup()
+        else:
+            return self.clazz.GetGroup(row - 1)
+
+    def SetClassGroup(self, row, group):
+        """Set the given row to properties of group."""
+        self.__SetRow(row, group)
+        self.GetView().Refresh()
+
+    def __Modified(self, mod = True):
+        """Adjust the modified flag.
+
+        mod -- if -1 set the modified flag to False, otherwise perform
+               an 'or' operation with the current value of the flag and
+               'mod'
+        """
+
+        if mod == -1:
+            self.modified = False
+        else:
+            self.modified = mod or self.modified
+
+    def IsModified(self):
+        """True if this table is considered modified."""
+        return self.modified
+
+    def DeleteRows(self, pos, numRows = 1):
+        """Deletes 'numRows' beginning at row 'pos'. 
+
+        The row representing the default group is not removed.
+
+        The table is considered modified if any rows are removed.
+        """
+
+        assert pos >= 0
+        old_len = self.GetNumberRows()
+        for row in range(pos, pos - numRows, -1):
+            group = self.GetClassGroup(row)
+            if row != 0:
+                self.clazz.RemoveGroup(row - 1)
+                self.__Modified()
+
+        if self.IsModified():
+            self.__NotifyRowChanges(old_len, self.GetNumberRows())
+
+    def AppendRows(self, numRows = 1):
+        """Append 'numRows' empty rows to the end of the table.
+
+        The table is considered modified if any rows are appended.
+        """
+
+        old_len = self.GetNumberRows()
+        for i in range(numRows):
+            np = ClassGroupSingleton()
+            self.__SetRow(None, np)
+
+        if self.IsModified():
+            self.__NotifyRowChanges(old_len, self.GetNumberRows())
+
+
+ID_PROPERTY_REVERT = 4002
+ID_PROPERTY_ADD = 4003
+ID_PROPERTY_GENCLASS = 4004
+ID_PROPERTY_REMOVE = 4005
+ID_PROPERTY_MOVEUP = 4006
+ID_PROPERTY_MOVEDOWN = 4007
+ID_PROPERTY_TRY = 4008
+ID_PROPERTY_EDITSYM = 4009
+ID_PROPERTY_SELECT = 4011
+ID_PROPERTY_TITLE = 4012
+ID_PROPERTY_FIELDTEXT = 4013
+
+BTN_ADD = 0
+BTN_EDIT = 1
+BTN_GEN = 2
+BTN_UP = 3
+BTN_DOWN = 4
+BTN_RM = 5
+
+EB_LAYER_TITLE = 0
+EB_SELECT_FIELD = 1
+EB_GEN_CLASS = 2
+
+class Classifier(LayerProperties):
+
+    type2string = {None:             _("None"),
+                   FIELDTYPE_STRING: _("Text"),
+                   FIELDTYPE_INT:    _("Integer"),
+                   FIELDTYPE_DOUBLE: _("Decimal")}
+
+    def __init__(self, parent, name, layer, group = None):
+        """Create a Properties/Classification dialog for a layer.
+        The layer is part of map. If group is not None, select that
+        group in the classification table.
+        """
+
+        LayerProperties.__init__(self, parent, name, layer)
+
+        self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
+                             self.layer_shapestore_replaced)
+
+        self.genDlg = None
+        self.group = group
+
+        LayerProperties.dialog_layout(self)
+
+    def dialog_layout(self, panel, panelBox):
+
+        if self.layer.HasClassification():
+
+            self.fieldTypeText = wx.StaticText(panel, -1, "")
+
+            self.originalClass = self.layer.GetClassification()
+            self.originalClassField = self.layer.GetClassificationColumn()
+            field = self.originalClassField
+            fieldType = self.layer.GetFieldType(field)
+
+            table = self.layer.ShapeStore().Table()
+            #
+            # make field choice box
+            #
+            self.fields = wx.Choice(panel, ID_PROPERTY_SELECT,)
+
+            self.num_cols = table.NumColumns()
+            # just assume the first field in case one hasn't been
+            # specified in the file.
+            self.__cur_field = 0
+
+            self.fields.Append("<None>")
+
+            if fieldType is None:
+                self.fields.SetClientData(0, copy.deepcopy(self.originalClass))
+            else:
+                self.fields.SetClientData(0, None)
+
+            for i in range(self.num_cols):
+                name = table.Column(i).name
+                self.fields.Append(name)
+
+                if name == field:
+                    self.__cur_field = i + 1
+                    self.fields.SetClientData(i + 1,
+                                              copy.deepcopy(self.originalClass))
+                else:
+                    self.fields.SetClientData(i + 1, None)
+
+            button_gen = wx.Button(panel, ID_PROPERTY_GENCLASS,
+                _("Generate Class"))
+            button_add = wx.Button(panel, ID_PROPERTY_ADD,
+                _("Add"))
+            button_moveup = wx.Button(panel, ID_PROPERTY_MOVEUP,
+                _("Move Up"))
+            button_movedown = wx.Button(panel, ID_PROPERTY_MOVEDOWN,
+                _("Move Down"))
+            button_edit = wx.Button(panel, ID_PROPERTY_EDITSYM,
+                _("Edit Symbol"))
+            button_remove = wx.Button(panel, ID_PROPERTY_REMOVE,
+                _("Remove"))
+
+            self.classGrid = ClassGrid(panel, self)
+
+            # calling __SelectField after creating the classGrid fills in the
+            # grid with the correct information
+            self.fields.SetSelection(self.__cur_field)
+            self.__SelectField(self.__cur_field, group = self.group)
+
+
+            classBox = wx.StaticBoxSizer(
+                        wx.StaticBox(panel, -1, _("Classification")), wx.VERTICAL)
+
+
+            sizer = wx.BoxSizer(wx.HORIZONTAL)
+            sizer.Add(wx.StaticText(panel, ID_PROPERTY_FIELDTEXT, _("Field: ")),
+                0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 4)
+            sizer.Add(self.fields, 1, wx.GROW | wx.ALL, 4)
+
+            classBox.Add(sizer, 0, wx.GROW, 4)
+
+            classBox.Add(self.fieldTypeText, 0,
+                        wx.GROW | wx.ALIGN_LEFT | wx.ALL | wx.ADJUST_MINSIZE, 4)
+
+            controlBox = wx.BoxSizer(wx.HORIZONTAL)
+            controlButtonBox = wx.BoxSizer(wx.VERTICAL)
+
+            controlButtonBox.Add(button_gen, 0, wx.GROW|wx.ALL, 4)
+            controlButtonBox.Add(button_add, 0, wx.GROW|wx.ALL, 4)
+            controlButtonBox.Add(button_moveup, 0, wx.GROW|wx.ALL, 4)
+            controlButtonBox.Add(button_movedown, 0, wx.GROW|wx.ALL, 4)
+            controlButtonBox.Add(button_edit, 0, wx.GROW|wx.ALL, 4)
+            controlButtonBox.Add( (60, 20), 0, wx.GROW|wx.ALL|wx.ALIGN_BOTTOM, 4)
+            controlButtonBox.Add(button_remove, 0,
+                                 wx.GROW|wx.ALL|wx.ALIGN_BOTTOM, 4)
+
+            controlBox.Add(self.classGrid, 1, wx.GROW, 0)
+            controlBox.Add(controlButtonBox, 0, wx.GROW, 10)
+
+            classBox.Add(controlBox, 1, wx.GROW, 10)
+            panelBox.Add(classBox, 1, wx.GROW, 0)
+
+
+        self.Bind(wx.EVT_CHOICE, self._OnFieldSelect, id=ID_PROPERTY_SELECT)
+        self.Bind(wx.EVT_BUTTON, self._OnAdd, id=ID_PROPERTY_ADD)
+        self.Bind(wx.EVT_BUTTON, self._OnEditSymbol, id=ID_PROPERTY_EDITSYM)
+        self.Bind(wx.EVT_BUTTON, self._OnRemove, id=ID_PROPERTY_REMOVE)
+        self.Bind(wx.EVT_BUTTON, self._OnGenClass, id=ID_PROPERTY_GENCLASS)
+        self.Bind(wx.EVT_BUTTON, self._OnMoveUp, id=ID_PROPERTY_MOVEUP)
+        self.Bind(wx.EVT_BUTTON, self._OnMoveDown, id=ID_PROPERTY_MOVEDOWN)
+
+    def unsubscribe_messages(self):
+        """Unsubscribe from all messages."""
+        LayerProperties.unsubscribe_messages(self)
+        self.layer.Unsubscribe(LAYER_SHAPESTORE_REPLACED,
+                               self.layer_shapestore_replaced)
+
+    def layer_shapestore_replaced(self, *args):
+        """Subscribed to the map's LAYER_SHAPESTORE_REPLACED message.
+        Close self.
+        """
+        self.Close()
+
+    def EditSymbol(self, row):
+        """Open up a dialog where the user can select the properties 
+        for a group.
+        """
+        table = self.classGrid.GetTable()
+        prop = table.GetValueAsCustom(row, COL_SYMBOL, None)
+
+        # get a new ClassGroupProperties object and copy the 
+        # values over to our current object
+        propDlg = SelectPropertiesDialog(self, prop, self.layer.ShapeType())
+
+        self.Enable(False)
+        if propDlg.ShowModal() == wx.ID_OK:
+            new_prop = propDlg.GetClassGroupProperties()
+            table.SetValueAsCustom(row, COL_SYMBOL, None, new_prop)
+        self.Enable(True)
+        propDlg.Destroy()
+
+    def _SetClassification(self, clazz):
+        """Called from the ClassGen dialog when a new classification has
+        been created and should be set in the table.
+        """
+        # FIXME: This could be implemented using a message
+
+        self.fields.SetClientData(self.__cur_field, clazz)
+        self.classGrid.GetTable().SetClassification(clazz)
+
+    def __BuildClassification(self, fieldIndex, copyClass=False, force=False):
+        """Pack the classification setting into a Classification object.
+        Returns (Classification, fieldName) where fieldName is the selected
+        field in the table that the classification should be used with.
+        """
+
+#       numRows = self.classGrid.GetNumberRows()
+#       assert numRows > 0  # there should always be a default row
+
+        if fieldIndex == 0:
+            fieldName = None
+            fieldType = None
+        else:
+            fieldName = self.fields.GetString(fieldIndex)
+            fieldType = self.layer.GetFieldType(fieldName)
+
+        clazz = self.fields.GetClientData(fieldIndex)
+        if clazz is None or self.classGrid.GetTable().IsModified() or force:
+            clazz = self.classGrid.GetTable().GetClassification()
+            if copyClass:
+                clazz = copy.deepcopy(clazz)
+
+        return clazz, fieldName
+
+    def __SetGridTable(self, fieldIndex, group = None):
+        """Set the table with the classification associated with the
+        selected field at fieldIndex. Select the specified group
+        if group is not None.
+        """
+
+        clazz = self.fields.GetClientData(fieldIndex)
+
+        if clazz is None:
+            clazz = Classification()
+            clazz.SetDefaultGroup(
+                ClassGroupDefault(
+                    self.layer.GetClassification().
+                               GetDefaultGroup().GetProperties()))
+
+        fieldName = self.fields.GetString(fieldIndex)
+        fieldType = self.layer.GetFieldType(fieldName)
+
+        self.classGrid.CreateTable(clazz, fieldType,
+                                   self.layer.ShapeType(), group)
+
+    def __SetFieldTypeText(self, fieldIndex):
+        """Set the field type string using the data type of the field
+        at fieldIndex.
+        """
+        fieldName = self.fields.GetString(fieldIndex)
+        fieldType = self.layer.GetFieldType(fieldName)
+
+        assert Classifier.type2string.has_key(fieldType)
+
+        text = Classifier.type2string[fieldType]
+
+        self.fieldTypeText.SetLabel(_("Data Type: %s") % text)
+
+    def __SelectField(self, newIndex, oldIndex = -1, group = None):
+        """This method assumes that the current selection for the
+        combo has already been set by a call to SetSelection().
+        """
+
+        assert oldIndex >= -1
+
+        if oldIndex != -1:
+            clazz, name = self.__BuildClassification(oldIndex, force = True)
+            self.fields.SetClientData(oldIndex, clazz)
+
+        self.__SetGridTable(newIndex, group)
+
+        self.__EnableButtons(EB_SELECT_FIELD)
+
+        self.__SetFieldTypeText(newIndex)
+
+    def __SetTitle(self, title):
+        """Set the title of the dialog."""
+        if title != "":
+            title = ": " + title
+
+        self.SetTitle(_("Layer Properties") + title)
+
+    def _OnEditSymbol(self, event):
+        """Open up a dialog for the user to select group properties."""
+        sel = self.classGrid.GetCurrentSelection()
+
+        if len(sel) == 1:
+            self.EditSymbol(sel[0])
+
+    def _OnFieldSelect(self, event):
+        index = self.fields.GetSelection()
+        self.__SelectField(index, self.__cur_field)
+        self.__cur_field = index
+
+    def OnTry(self, event):
+        """Put the data from the table into a new Classification and hand
+           it to the layer.
+        """
+
+        if self.layer.HasClassification():
+            clazz = self.fields.GetClientData(self.__cur_field)
+
+            #
+            # only build the classification if there wasn't one to
+            # to begin with or it has been modified
+            #
+            self.classGrid.SaveEditControlValue()
+            clazz, name = self.__BuildClassification(self.__cur_field, True)
+
+            self.layer.SetClassificationColumn(name)
+            self.layer.SetClassification(clazz)
+
+        self.haveApplied = True
+
+    def OnOK(self, event):
+        self.OnTry(event)
+        self.Close()
+
+    def OnRevert(self, event):
+        """The layer's current classification stays the same."""
+        if self.haveApplied and self.layer.HasClassification():
+            self.layer.SetClassificationColumn(self.originalClassField)
+            self.layer.SetClassification(self.originalClass)
+
+        #self.Close()
+
+    def _OnAdd(self, event):
+        self.classGrid.AppendRows()
+
+    def _OnRemove(self, event):
+        self.classGrid.DeleteSelectedRows()
+
+    def _OnGenClass(self, event):
+        """Open up a dialog for the user to generate classifications."""
+
+        self.genDlg = ClassGenDialog(self, self.layer,
+                          self.fields.GetString(self.__cur_field))
+
+        self.Bind(wx.EVT_CLOSE, self._OnGenDialogClose, self.genDlg)
+
+        self.__EnableButtons(EB_GEN_CLASS)
+
+        self.genDlg.Show()
+
+    def _OnGenDialogClose(self, event):
+        """Reenable buttons after the generate classification 
+        dialog is closed.
+        """
+        self.genDlg.Destroy()
+        self.genDlg = None
+        self.__EnableButtons(EB_GEN_CLASS)
+
+    def _OnMoveUp(self, event):
+        """When the user clicks MoveUp, try to move a group up one row."""
+        sel = self.classGrid.GetCurrentSelection()
+
+        if len(sel) == 1:
+            i = sel[0]
+            if i > 1:
+                table = self.classGrid.GetTable()
+                x = table.GetClassGroup(i - 1)
+                y = table.GetClassGroup(i)
+                table.SetClassGroup(i - 1, y)
+                table.SetClassGroup(i, x)
+                self.classGrid.ClearSelection()
+                self.classGrid.SelectRow(i - 1)
+                self.classGrid.MakeCellVisible(i - 1, 0)
+
+    def _OnMoveDown(self, event):
+        """When the user clicks MoveDown, try to move a group down one row."""
+        sel = self.classGrid.GetCurrentSelection()
+
+        if len(sel) == 1:
+            i = sel[0]
+            table = self.classGrid.GetTable()
+            if 0 < i < table.GetNumberRows() - 1:
+                x = table.GetClassGroup(i)
+                y = table.GetClassGroup(i + 1)
+                table.SetClassGroup(i, y)
+                table.SetClassGroup(i + 1, x)
+                self.classGrid.ClearSelection()
+                self.classGrid.SelectRow(i + 1)
+                self.classGrid.MakeCellVisible(i + 1, 0)
+
+    def _OnTitleChanged(self, event):
+        """Update the dialog title when the user changed the layer name."""
+        obj = event.GetEventObject()
+
+        self.layer.SetTitle(obj.GetValue())
+        self.__SetTitle(self.layer.Title())
+
+        self.__EnableButtons(EB_LAYER_TITLE)
+
+    def __EnableButtons(self, case):
+        """Helper method that enables/disables the appropriate buttons
+        based on the case provided. Cases are constants beginning with EB_.
+        """
+
+        list = {wx.ID_OK                 : True,
+                wx.ID_CANCEL             : True,
+                ID_PROPERTY_ADD         : True,
+                ID_PROPERTY_MOVEUP      : True,
+                ID_PROPERTY_MOVEDOWN    : True,
+                ID_PROPERTY_REMOVE      : True,
+                ID_PROPERTY_SELECT      : True,
+                ID_PROPERTY_FIELDTEXT   : True,
+                ID_PROPERTY_GENCLASS    : True,
+                ID_PROPERTY_EDITSYM     : True}
+
+        if case == EB_LAYER_TITLE:
+            if self.layer.Title() == "":
+                list[wxID_OK] = False
+                list[wxID_CANCEL] = False
+
+        elif case == EB_SELECT_FIELD:
+            if self.fields.GetSelection() == 0:
+                list[ID_PROPERTY_GENCLASS] = False
+                list[ID_PROPERTY_ADD] = False
+                list[ID_PROPERTY_MOVEUP] = False
+                list[ID_PROPERTY_MOVEDOWN] = False
+                list[ID_PROPERTY_REMOVE] = False
+
+        elif case == EB_GEN_CLASS:
+            if self.genDlg is not None:
+                list[ID_PROPERTY_SELECT] = False
+                list[ID_PROPERTY_FIELDTEXT] = False
+                list[ID_PROPERTY_GENCLASS] = False
+
+        for id, enable in list.items():
+            win = self.FindWindowById(id)
+            if win:
+                win.Enable(enable)
+
+ID_SELPROP_SPINCTRL_LINEWIDTH = 4002
+ID_SELPROP_PREVIEW = 4003
+ID_SELPROP_STROKECLR = 4004
+ID_SELPROP_FILLCLR = 4005
+ID_SELPROP_STROKECLRTRANS = 4006
+ID_SELPROP_FILLCLRTRANS = 4007
+ID_SELPROP_SPINCTRL_SIZE = 4008
+
+class SelectPropertiesDialog(wx.Dialog):
+    """Dialog that allows the user to select group properties."""
+
+    def __init__(self, parent, prop, shapeType):
+        """Open the dialog with the initial prop properties and shapeType."""
+
+        wx.Dialog.__init__(self, parent, -1, _("Select Properties"),
+                          style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
+
+        self.prop = ClassGroupProperties(prop)
+
+        topBox = wx.BoxSizer(wx.VERTICAL)
+
+        itemBox = wx.BoxSizer(wx.HORIZONTAL)
+
+        # preview box
+        previewBox = wx.BoxSizer(wx.VERTICAL)
+        previewBox.Add(wx.StaticText(self, -1, _("Preview:")),
+            0, wx.ALIGN_LEFT | wx.ALL, 4)
+
+        self.previewWin = ClassGroupPropertiesCtrl(
+            self, ID_SELPROP_PREVIEW, self.prop, shapeType,
+            (40, 40), wx.SIMPLE_BORDER)
+
+        self.previewWin.AllowEdit(False)
+
+        previewBox.Add(self.previewWin, 1, wx.GROW | wx.ALL, 4)
+
+        itemBox.Add(previewBox, 1, wx.ALIGN_LEFT | wx.ALL | wx.GROW, 0)
+
+        # control box
+        ctrlBox = wx.BoxSizer(wx.VERTICAL)
+
+        lineColorBox = wx.BoxSizer(wx.HORIZONTAL)
+        button = wx.Button(self, ID_SELPROP_STROKECLR, _("Change Line Color"))
+        button.SetFocus()
+        lineColorBox.Add(button, 1, wx.ALL | wx.GROW, 4)
+        self.Bind(wx.EVT_BUTTON, self._OnChangeLineColor, id=ID_SELPROP_STROKECLR)
+
+        lineColorBox.Add(
+            wx.Button(self, ID_SELPROP_STROKECLRTRANS, _("Transparent")),
+            1, wx.ALL | wx.GROW, 4)
+        self.Bind(wx.EVT_BUTTON, self._OnChangeLineColorTrans, \
+                                   id=ID_SELPROP_STROKECLRTRANS)
+
+        ctrlBox.Add(lineColorBox, 0,
+                    wx.ALIGN_CENTER_HORIZONTAL | wx.ALL | wx.GROW, 4)
+
+        if shapeType != SHAPETYPE_ARC:
+            fillColorBox = wx.BoxSizer(wx.HORIZONTAL)
+            fillColorBox.Add(
+                wx.Button(self, ID_SELPROP_FILLCLR, _("Change Fill Color")),
+                1, wx.ALL | wx.GROW, 4)
+            self.Bind(wx.EVT_BUTTON, self._OnChangeFillColor, id=ID_SELPROP_FILLCLR)
+            fillColorBox.Add(
+                wx.Button(self, ID_SELPROP_FILLCLRTRANS, _("Transparent")),
+                1, wx.ALL | wx.GROW, 4)
+            self.Bind(wx.EVT_BUTTON, self._OnChangeFillColorTrans,\
+                                        id=ID_SELPROP_FILLCLRTRANS)
+            ctrlBox.Add(fillColorBox, 0,
+                        wx.ALIGN_CENTER_HORIZONTAL | wx.ALL | wx.GROW, 4)
+
+        # Line width selection
+        spinBox = wx.BoxSizer(wx.HORIZONTAL)
+        spinBox.Add(wx.StaticText(self, -1, _("Line Width: ")),
+                0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 4)
+        self.spinCtrl_linewidth = wx.SpinCtrl(self,
+                                             ID_SELPROP_SPINCTRL_LINEWIDTH,
+                                             min=1, max=10,
+                                             value=str(prop.GetLineWidth()),
+                                             initial=prop.GetLineWidth())
+
+        self.Bind(wx.EVT_SPINCTRL, self._OnSpinLineWidth, \
+                    id=ID_SELPROP_SPINCTRL_LINEWIDTH)
+
+        spinBox.Add(self.spinCtrl_linewidth, 0, wx.ALIGN_LEFT | wx.ALL, 4)
+        ctrlBox.Add(spinBox, 0, wx.ALIGN_RIGHT | wx.ALL, 0)
+
+        # Size selection
+        if shapeType == SHAPETYPE_POINT:
+            spinBox = wx.BoxSizer(wx.HORIZONTAL)
+            spinBox.Add(wx.StaticText(self, -1, _("Size: ")),
+                        0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 4)
+            self.spinCtrl_size = wx.SpinCtrl(self, ID_SELPROP_SPINCTRL_SIZE,
+                                            min=1, max=100,
+                                            value=str(prop.GetSize()),
+                                            initial=prop.GetSize())
+
+            self.Bind(wx.EVT_SPINCTRL, self._OnSpinSize, id=ID_SELPROP_SPINCTRL_SIZE)
+
+            spinBox.Add(self.spinCtrl_size, 0, wx.ALIGN_LEFT | wx.ALL, 4)
+            ctrlBox.Add(spinBox, 0, wx.ALIGN_RIGHT | wx.ALL, 0)
+
+
+        itemBox.Add(ctrlBox, 0, wx.ALIGN_RIGHT | wx.ALL | wx.GROW, 0)
+        topBox.Add(itemBox, 1, wx.ALIGN_LEFT | wx.ALL | wx.GROW, 0)
+
+        #
+        # Control buttons:
+        #
+        buttonBox = wx.BoxSizer(wx.HORIZONTAL)
+        button_ok = wx.Button(self, wx.ID_OK, _("OK"))
+        buttonBox.Add(button_ok, 0, wx.RIGHT|wx.EXPAND, 10)
+        buttonBox.Add(wx.Button(self, wx.ID_CANCEL, _("Cancel")),
+                      0, wx.RIGHT|wx.EXPAND, 10)
+        topBox.Add(buttonBox, 0, wx.ALIGN_RIGHT|wx.BOTTOM|wx.TOP, 10)
+
+        button_ok.SetDefault()
+
+        #EVT_BUTTON(self, wxID_OK, self._OnOK)
+        #EVT_BUTTON(self, ID_SELPROP_CANCEL, self._OnCancel)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(topBox)
+        topBox.Fit(self)
+        topBox.SetSizeHints(self)
+
+    def OnOK(self, event):
+        self.EndModal(wx.ID_OK)
+
+    def OnCancel(self, event):
+        self.EndModal(wx.ID_CANCEL)
+
+    def _OnSpinLineWidth(self, event):
+        self.prop.SetLineWidth(self.spinCtrl_linewidth.GetValue())
+        self.previewWin.Refresh()
+
+    def _OnSpinSize(self, event):
+        self.prop.SetSize(self.spinCtrl_size.GetValue())
+        self.previewWin.Refresh()
+
+    def __GetColor(self, cur):
+        dialog = ColorDialog(self)
+        dialog.SetColor(cur)
+
+        ret = None
+        if dialog.ShowModal() == wx.ID_OK:
+            ret = dialog.GetColor()
+
+        dialog.Destroy()
+
+        return ret
+
+    def _OnChangeLineColor(self, event):
+        clr = self.__GetColor(self.prop.GetLineColor())
+        if clr is not None:
+            self.prop.SetLineColor(clr)
+        self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
+
+    def _OnChangeLineColorTrans(self, event):
+        self.prop.SetLineColor(Transparent)
+        self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
+
+    def _OnChangeFillColor(self, event):
+        clr = self.__GetColor(self.prop.GetFill())
+        if clr is not None:
+            self.prop.SetFill(clr)
+        self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
+
+    def _OnChangeFillColorTrans(self, event):
+        self.prop.SetFill(Transparent)
+        self.previewWin.Refresh() # XXX: work around, see ClassDataPreviewer
+
+    def GetClassGroupProperties(self):
+        return self.prop
+
+
+class ClassDataPreviewWindow(wx.Window):
+    """A custom window that draws group properties using the correct shape."""
+
+    def __init__(self, rect, prop, shapeType,
+                       parent = None, id = -1, size = wx.DefaultSize):
+        """Draws the appropriate shape as specified with shapeType using
+        prop properities.
+        """
+        if parent is not None:
+            wx.Window.__init__(self, parent, id, (0, 0), size)
+            self.Bind(wx.EVT_PAINT, self._OnPaint)
+
+        self.rect = rect
+
+        self.prop = prop
+        self.shapeType = shapeType
+        self.previewer = ClassDataPreviewer()
+
+    def GetProperties():
+        return self.prop
+
+    def _OnPaint(self, event):
+        dc = wx.PaintDC(self)
+
+        # XXX: this doesn't seem to be having an effect:
+        dc.DestroyClippingRegion()
+
+        if self.rect is None:
+            w, h = self.GetSize()
+            rect = wx.Rect(0, 0, w, h)
+        else:
+            rect = self.rect
+
+        self.previewer.Draw(dc, rect, self.prop, self.shapeType)
+
+class ClassDataPreviewer:
+    """Class that actually draws a group property preview."""
+
+    def Draw(self, dc, rect, prop, shapeType):
+        """Draw the property.
+
+        returns: (w, h) as adapted extend if the drawing size
+        exceeded the given rect. This can only be the case
+        for point symbols. If the symbol fits the given rect,
+        None is returned.
+        """
+
+        assert dc is not None
+        assert isinstance(prop, ClassGroupProperties)
+
+        if rect is None:
+            x = 0
+            y = 0
+            w, h = dc.GetSize()
+        else:
+            x = rect.GetX()
+            y = rect.GetY()
+            w = rect.GetWidth()
+            h = rect.GetHeight()
+
+        stroke = prop.GetLineColor()
+        if stroke is Transparent:
+            pen = wx.TRANSPARENT_PEN
+        else:
+            pen = wx.Pen(Color2wxColour(stroke),
+                        prop.GetLineWidth(),
+                        wx.SOLID)
+
+        stroke = prop.GetFill()
+        if stroke is Transparent:
+            brush = wx.TRANSPARENT_BRUSH
+        else:
+            brush = wx.Brush(Color2wxColour(stroke), wx.SOLID)
+
+        dc.SetPen(pen)
+        dc.SetBrush(brush)
+
+        if shapeType == SHAPETYPE_ARC:
+            dc.DrawSpline([wx.Point(x, y + h),
+                           wx.Point(x + w/2, y + h/4),
+                           wx.Point(x + w/2, y + h/4*3),
+                           wx.Point(x + w, y)])
+
+        elif shapeType == SHAPETYPE_POINT:
+
+            dc.DrawCircle(x + w/2, y + h/2, prop.GetSize())
+            circle_size =  prop.GetSize() * 2 + prop.GetLineWidth() * 2
+            new_h = h
+            new_w = w
+            if h < circle_size: new_h = circle_size
+            if w < circle_size: new_w = circle_size
+            if new_h > h or new_w > w:
+                return (new_w, new_h)
+
+        elif shapeType == SHAPETYPE_POLYGON:
+            dc.DrawRectangle(x, y, w, h)
+
+        return None
+
+class ClassRenderer(grid.PyGridCellRenderer):
+    """A wrapper class that can be used to draw group properties in a
+    grid table.
+    """
+
+    def __init__(self, shapeType):
+        grid.PyGridCellRenderer.__init__(self)
+        self.shapeType = shapeType
+        self.previewer = ClassDataPreviewer()
+
+    def Draw(self, grid, attr, dc, rect, row, col, isSelected):
+        data = grid.GetTable().GetClassGroup(row)
+
+        dc.SetClippingRegion(rect.GetX(), rect.GetY(),
+                             rect.GetWidth(), rect.GetHeight())
+        dc.SetPen(wx.Pen(wx.LIGHT_GREY))
+        dc.SetBrush(wx.Brush(wx.LIGHT_GREY, wx.SOLID))
+        dc.DrawRectangle(rect.GetX(), rect.GetY(),
+                         rect.GetWidth(), rect.GetHeight())
+
+        if not isinstance(data, ClassGroupMap):
+            new_size = self.previewer.Draw(dc, rect, data.GetProperties(),
+                                           self.shapeType)
+            if new_size is not None:
+                (new_w, new_h) = new_size
+                grid.SetRowSize(row, new_h)
+                grid.SetColSize(col, new_h)
+                grid.ForceRefresh()
+
+                # now that we know the height, redraw everything
+                rect.SetHeight(new_h)
+                rect.SetWidth(new_w)
+                dc.DestroyClippingRegion()
+                dc.SetClippingRegion(rect.GetX(), rect.GetY(),
+                                     rect.GetWidth(), rect.GetHeight())
+                dc.SetPen(wx.Pen(wx.LIGHT_GREY))
+                dc.SetBrush(wx.Brush(wx.LIGHT_GREY, wx.SOLID))
+                dc.DrawRectangle(rect.GetX(), rect.GetY(),
+                                 rect.GetWidth(), rect.GetHeight())
+                self.previewer.Draw(dc, rect, data.GetProperties(),
+                                    self.shapeType)
+
+        if isSelected:
+            dc.SetPen(wx.Pen(wx.BLACK, 1, wx.SOLID))
+            dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+            dc.DrawRectangle(rect.GetX(), rect.GetY(),
+                             rect.GetWidth(), rect.GetHeight())
+
+        dc.DestroyClippingRegion()
+
+
+class ClassGroupPropertiesCtrl(wx.Control):
+    """A custom window and control that draw a preview of group properties
+    and can open a dialog to modify the properties if the user double-clicks
+    it.
+    """
+
+    def __init__(self, parent, id, props, shapeType,
+                 size = wx.DefaultSize, style = 0):
+        wx.Control.__init__(self, parent, id, size = size, style = style)
+
+        self.parent = parent
+
+        self.SetProperties(props)
+        self.SetShapeType(shapeType)
+        self.AllowEdit(True)
+
+        self.Bind(wx.EVT_PAINT, self._OnPaint)
+        self.Bind(wx.EVT_LEFT_DCLICK, self._OnLeftDClick)
+
+        self.previewer = ClassDataPreviewer()
+
+    def _OnPaint(self, event):
+        dc = wx.PaintDC(self)
+
+        # XXX: this doesn't seem to be having an effect:
+        dc.DestroyClippingRegion()
+
+        w, h = self.GetClientSize()
+
+        self.previewer.Draw(dc,
+                            wx.Rect(0, 0, w, h),
+                            self.GetProperties(),
+                            self.GetShapeType())
+
+
+    def GetProperties(self):
+        return self.props
+
+    def SetProperties(self, props):
+        self.props = props
+        self.Refresh()
+
+    def GetShapeType(self):
+        return self.shapeType
+
+    def SetShapeType(self, shapeType):
+        self.shapeType = shapeType
+        self.Refresh()
+
+    def AllowEdit(self, allow):
+        """Allow/Disallow double-clicking on the control."""
+        self.allowEdit = allow
+
+    def DoEdit(self):
+        """Open the properties selector dialog."""
+
+        if not self.allowEdit: return
+
+        propDlg = SelectPropertiesDialog(self.parent,
+                                         self.GetProperties(),
+                                         self.GetShapeType())
+
+        if propDlg.ShowModal() == wx.ID_OK:
+            new_prop = propDlg.GetClassGroupProperties()
+            self.SetProperties(new_prop)
+            self.Refresh()
+
+        propDlg.Destroy()
+
+    def _OnLeftDClick(self, event):
+        self.DoEdit()
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/colordialog.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/colordialog.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/colordialog.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,136 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagnber <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: colordialog.py 2700 2006-09-18 14:27:02Z dpinte $
+
+import wx
+
+from Thuban import _
+
+from Thuban.UI.common import Color2wxColour, wxColour2Color
+
+from Thuban.Model.color import Transparent
+
+
+# determine whether the pyColourChooserDialog is available
+# It was not available with the very first versions of wxWindows 2.4
+# (I don't know the exact version though)
+try:
+    from wxPython.lib.colourchooser import wxPyColourChooser
+    _wxPyColourChooser = True
+    wx.InitAllImageHandlers() # should be somewhere at Thuban startup?
+except:
+    _wxPyColourChooser = False
+
+
+class PyColorChooserDialog(wx.Dialog):
+    """
+    A Dialog that uses the wxPyColourChooser Frame and simply
+    adds OK and Cancel button to form a modal color selection dialog.
+    """
+
+    def __init__(self, parent):
+        wx.Dialog.__init__(self, parent, -1, _("Select Color"))
+
+        self.parent = parent
+        self.dialog_layout()
+
+    def dialog_layout(self):
+        top_box = wx.BoxSizer(wx.VERTICAL)
+
+        self.chooser = wxPyColourChooser(self, -1)
+
+        top_box.Add(self.chooser, 1, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        box.Add(wx.Button(self, wx.ID_OK, _("OK")), 0, wx.ALL, 4)
+        box.Add(wx.Button(self, wx.ID_CANCEL, _("Cancel")), 0, wx.ALL, 4)
+        top_box.Add(box, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 10)
+
+        self.Bind(wx.EVT_BUTTON, self.OnOK, id=wx.ID_OK)
+        self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(top_box)
+        top_box.Fit(self)
+        top_box.SetSizeHints(self)
+
+    def GetValue(self):
+        return self.chooser.GetValue()
+
+    def SetValue(self, color):
+        return self.chooser.SetValue(color)
+
+    def OnOK(self, event):
+        self.EndModal(wx.ID_OK)
+
+    def OnCancel(self, event):
+        self.EndModal(wx.ID_CANCEL)
+
+
+class ColorDialog:
+    """
+    The color dialog raises one of the available color selection
+    dialogs. ColorDialog is no derived from any GUI class though.
+
+    Furthermore, wxColour class is mapped to the Thuban
+    Color class already through this class.
+
+    Eventually it should be configurable globally for Thuban
+    which color dialog to use since they might differ in
+    functionality, translation or stability.
+    """
+
+    def __init__(self, parent):
+        if _wxPyColourChooser:
+            self.dlg = PyColorChooserDialog(parent)
+        else:
+            self.dlg = wx.ColourDialog(parent)
+
+    def GetColor(self):
+        if _wxPyColourChooser:
+            return wxColour2Color(self.dlg.GetValue())
+        else:
+            return wxColour2Color(self.dlg.GetColourData().GetColour())
+
+    def SetColor(self, color):
+        if color is not Transparent:
+            if _wxPyColourChooser:
+                self.dlg.SetValue(Color2wxColour(color))
+            else:
+                self.dlg.GetColourData().SetColour(Color2wxColour(color))
+
+    def ShowModal(self):
+        return self.dlg.ShowModal()
+
+    def Destroy(self):
+        return self.dlg.Destroy()
+
+
+if __name__ == "__main__":
+    # Test routine to run the dialog without Thuban
+
+    from wxPython.wx import wxApp, NULL
+
+    wx.InitAllImageHandlers()
+
+    class _TestApp(wx.App):
+        def OnInit(self):
+            dialog = ColorDialog(NULL)
+
+            if dialog.ShowModal() == wx.ID_OK:
+                print "Selected color:", dialog.GetColor()
+            else:
+                print "No color selected"
+
+            dialog.Destroy()
+            return True
+
+    app = _TestApp()
+    app.MainLoop()

Added: packages/thuban/branches/upstream/current/Thuban/UI/command.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/command.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/command.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,154 @@
+# Copyright (C) 2001, 2002 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Command Objects.
+
+Command objects represent a command that a user can invoke and act as
+mediators between the GUI and the application.
+
+This module also defines a command registry that maps command names to
+command objects.
+"""
+
+__version__ = "$Revision: 2700 $"
+
+
+from types import TupleType
+
+
+class Command:
+
+    """
+    Represent a single command.
+
+    A command is identified by a name, it has a title (used in menu
+    items and buttons, etc) and a callable object that can be invoked
+    with the context as a single parameter. The context is an object
+    with a few public attributes for the application object, the session
+    and the main window.
+
+    Additionally, a command may have functions that can determine
+    whether the command can be invoked or whether it is checked in case
+    of a toggled command. These functions are called with just the
+    context as parameters.
+    """
+
+    args = ()
+    kwargs = None
+    sensitive  = None
+    checked = None
+    dyntext = None
+
+    def __init__(self, name, title, function, helptext = "", icon = "",
+                 args = (), kwargs = None,
+                 sensitive = None, checked = None, dyntext = None):
+        self.name = name
+        self.title = title
+        self.function = function
+        self.helptext = helptext
+        self.icon = icon
+        if args != ():
+            if type(args) != TupleType:
+                args = (args,)
+            self.args = args
+        if kwargs is not None:
+            self.kwargs = kwargs
+        if sensitive is not None:
+            self.sensitive = sensitive
+        if checked is not None:
+            self.checked = checked
+        if dyntext is not None:
+            self.dyntext = dyntext
+
+    def Name(self):
+        return self.name
+
+    def Title(self):
+        return self.title
+
+    def HelpText(self):
+        return self.helptext
+
+    def Icon(self):
+        return self.icon
+
+    def Sensitive(self, context):
+        if self.sensitive is not None:
+            return self.sensitive(context)
+        return 1
+
+    def Checked(self, context):
+        if self.checked is not None:
+            return self.checked(context)
+        return 0 # XXX raise an exception?
+
+    def IsCheckCommand(self):
+        return self.checked is not None
+
+    def DynText(self, context):
+        if self.dyntext is not None:
+            return self.dyntext(context)
+        return self.Title()
+
+    def HasDynText(self):
+        return self.dyntext is not None
+
+    def IsDynamic(self):
+        """Return true if the command is in any way dynamic"""
+        return (self.sensitive is not None
+                or self.checked is not None
+                or self.dyntext is not None)
+
+    def IsTool(self):
+        """Return whether the command represents a tool.
+
+        This default implementation always returns 0.
+        """
+        return 0
+
+    def Execute(self, context, args = ()):
+        kw = self.kwargs
+        if kw is None:
+            kw = {}
+        if type(args) != TupleType:
+            args = (args,)
+        #print self.name, self.args, args
+        apply(self.function, (context,) + self.args + args, kw)
+
+class ToolCommand(Command):
+
+    """A command tool activating a tool"""
+
+    def IsTool(self):
+        """Return whether the command represents a tool, i.e. always 1"""
+        return 1
+
+
+class CommandRegistry:
+
+    """
+    A CommandRegistry maps command names to command objects
+    """
+
+    def __init__(self):
+        self.registry = {}
+
+    def Add(self, script):
+        self.registry[script.name] = script
+
+    def AddFunction(self, name, title, function, args = (), sensitive = None):
+        self.Add(Command(name, title, function, args = args,
+                         sensitive = sensitive))
+
+    def Command(self, name):
+        return self.registry.get(name, None)
+
+
+
+# The central command registry
+registry = CommandRegistry()

Added: packages/thuban/branches/upstream/current/Thuban/UI/common.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/common.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/common.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,52 @@
+# Copyright (c) 2001, 2003 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Miscellaneous UI related functions"""
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: common.py 2700 2006-09-18 14:27:02Z dpinte $
+
+
+from Thuban.Model.color import Color
+import wx
+
+def Color2wxColour(color):
+    """Return a wxColor object for the Thuban color object color"""
+    return wx.Colour(int(round(color.red * 255)),
+                    int(round(color.green * 255)),
+                    int(round(color.blue * 255)))
+
+def wxColour2Color(colour):
+    """Return a Thuban color object for the wxColor object color"""
+    assert(colour is not None)
+    # this doesn't work because colour is really a wxColourPtr!
+    #assert(isinstance(colour, wxColour))
+    return Color(colour.Red()   / 255.0,
+                 colour.Green() / 255.0,
+                 colour.Blue()  / 255.0)
+
+def ThubanBeginBusyCursor():
+    """Thuban wrapper for wxBeginBusyCursor
+
+    In addition to calling wxBeginBusyCursor this function also calls
+    wxSafeYield to make sure that the cursor change takes effect. wxGTK
+    2.4 at least doesn't do that automatically.
+
+    This function and the corresponding ThubanEndBusyCursor function are
+    the functions to use in Thuban to set a busy cursor.
+    """
+    wx.BeginBusyCursor()
+    wx.SafeYield()
+
+def ThubanEndBusyCursor():
+    """Thuban wrapper for wxEndBusyCursor
+
+    This function doesn't do anything more than calling wxEndBusyCursor
+    yet, but please use this whereever you use ThubanBeginBusyCursor.
+    """
+    wx.EndBusyCursor()

Added: packages/thuban/branches/upstream/current/Thuban/UI/context.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/context.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/context.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,29 @@
+# Copyright (C) 2001, 2002 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+The command execution context,
+"""
+
+__version__ = "$Revision: 374 $"
+
+class Context:
+
+    """Command Execution Context
+
+    Public Attributes:
+
+       application -- The application object
+       session -- The session object
+       mainwindow -- The main window
+
+    """
+
+    def __init__(self, application, session, mainwindow):
+        self.application = application
+        self.session = session
+        self.mainwindow = mainwindow

Added: packages/thuban/branches/upstream/current/Thuban/UI/controls.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/controls.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/controls.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,230 @@
+# Copyright (c) 2001, 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+
+"""Common Thuban specific control widgets"""
+
+__version__ = "$Revision: 2718 $"
+
+import wx
+from wx import grid
+
+from Thuban import _
+
+# FIXME: the wx_value_type_map should be moved from tableview to a
+# separate module
+from tableview import wx_value_type_map
+
+
+
+class RecordListCtrl(wx.ListCtrl):
+
+    """List Control showing a single record from a thuban table"""
+
+    def __init__(self, parent, id):
+        wx.ListCtrl.__init__(self, parent, id, style = wx.LC_REPORT)
+
+        self.InsertColumn(0, _("Field"))
+        self.SetColumnWidth(0, 200)
+        self.InsertColumn(1, _("Value"))
+        self.SetColumnWidth(1, 100)
+
+        # vaues maps row numbers to the corresponding python values
+        self.values = {}
+
+    def fill_list(self, table, shape):
+        """Fill self with the contents shape's record from table"""
+        self.DeleteAllItems()
+        values = {}
+
+        if shape is not None:
+            names = []
+            for col in table.Columns():
+                names.append(col.name)
+            record = table.ReadRowAsDict(shape)
+
+            for i in range(len(names)):
+                name = names[i]
+                value = record[name]
+                self.InsertStringItem(i, name)
+                self.SetStringItem(i, 1, str(value).decode('iso-8859-1'))
+                values[i] = value
+
+        self.values = values
+
+class SelectableRecordListCtrl(RecordListCtrl):
+
+    def __init__(self, parent, id):
+        RecordListCtrl.__init__(self, parent, id)
+
+        # selected is the index of the selected record or -1 if none is
+        # selected
+        self.selected = -1
+        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, id=self.GetId())
+
+    def OnItemSelected(self, event):
+        """Event handler. Update the selected instvar"""
+        self.selected = event.m_itemIndex
+
+    def GetValue(self):
+        """Return the currently selected value. None if no value is selected"""
+        if self.selected >= 0:
+            return self.values[self.selected]
+        else:
+            return None
+
+
+class RecordTable(grid.PyGridTableBase):
+
+    """Wrapper that makes a Thuban table record look like a table for a
+       wxGrid
+    """
+
+    def __init__(self, table = None, record = None):
+        grid.PyGridTableBase.__init__(self)
+        self.num_cols = 1
+        self.num_rows = 0
+        self.table = None
+        self.record_index = record
+        self.record = None
+        self.SetTable(table, record)
+
+    def SetTable(self, table, record_index):
+        old_num_rows = self.num_rows
+        if record_index is not None:
+            self.table = table
+            self.record_index = record_index
+            self.record = table.ReadRowAsDict(record_index)
+
+            # we have one row for each field in the table
+            self.num_rows = table.NumColumns()
+
+            # extract the field types and names of the row we're showing.
+            self.rows = []
+            for i in range(self.num_rows):
+                col = table.Column(i)
+                self.rows.append((col.name, wx_value_type_map[col.type]))
+            self.notify_get_values()
+        else:
+            # make the grid empty
+            self.num_rows = 0
+            self.rows = []
+
+        # notify the views if the number of rows has changed
+        if self.num_rows > old_num_rows:
+            self.notify_append_rows(self.num_rows - old_num_rows)
+        elif self.num_rows < old_num_rows:
+            self.notify_delete_rows(0, old_num_rows - self.num_rows)
+
+    def notify_append_rows(self, num):
+        """Tell the view that num rows were appended"""
+        self.send_view_message(grid.GRIDTABLE_NOTIFY_ROWS_APPENDED, num)
+
+    def notify_delete_rows(self, start, num):
+        """Tell the view that num rows were deleted starting at start"""
+        self.send_view_message(grid.GRIDTABLE_NOTIFY_ROWS_DELETED, start, num)
+
+    def notify_get_values(self):
+        """Tell the view that the grid's values have to be updated"""
+        self.send_view_message(grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
+
+    def send_view_message(self, msgid, *args):
+        """Send the message msgid to the view with arguments args"""
+        view = self.GetView()
+        if view:
+            #print "send_view_message", msgid, args
+            msg = apply(grid.GridTableMessage, (self, msgid) + args)
+            view.ProcessTableMessage(msg)
+
+    #
+    # required methods for the wxPyGridTableBase interface
+    #
+
+    def GetNumberRows(self):
+        return self.num_rows
+
+    def GetNumberCols(self):
+        return self.num_cols
+
+    def IsEmptyCell(self, row, col):
+        return row >= self.num_rows or col >= self.num_cols
+
+    # Get/Set values in the table.  The Python version of these
+    # methods can handle any data-type, (as long as the Editor and
+    # Renderer understands the type too,) not just strings as in the
+    # C++ version.
+    def GetValue(self, row, col):
+        if row < self.num_rows:
+            return self.record[self.rows[row][0]]
+        return ""
+
+    def SetValue(self, row, col, value):
+        if row < self.num_rows:
+            name = self.rows[row][0]
+            self.record[name] = value
+            self.table.write_record(self.record_index, {name: value})
+
+    #
+    # Some optional methods
+    #
+
+    # Called when the grid needs to display labels
+    def GetColLabelValue(self, col):
+        return _("Value")
+
+    def GetRowLabelValue(self, row):
+        if row < self.num_rows:
+            return self.rows[row][0]
+        return ""
+
+    # Called to determine the kind of editor/renderer to use by
+    # default, doesn't necessarily have to be the same type used
+    # nativly by the editor/renderer if they know how to convert.
+    def GetTypeName(self, row, col):
+        # for some reason row and col may be negative sometimes, but
+        # it's probably a wx bug (filed as #593189 on sourceforge)
+        if 0 <= row < self.num_rows:
+            return self.rows[row][1]
+        return grid.GRID_VALUE_STRING
+
+    # Called to determine how the data can be fetched and stored by the
+    # editor and renderer.  This allows you to enforce some type-safety
+    # in the grid.
+    def CanGetValueAs(self, row, col, typeName):
+        # perhaps we should allow conversion int->double?
+        return self.GetTypeName(row, col) == typeName
+
+    def CanSetValueAs(self, row, col, typeName):
+        return self.CanGetValueAs(row, col, typeName)
+
+
+
+class RecordGridCtrl(grid.Grid):
+
+    """Grid view for a RecordTable"""
+
+    def __init__(self, parent, table = None, record = None):
+        grid.Grid.__init__(self, parent, -1)
+
+        self.table = RecordTable(table, record)
+
+        # The second parameter means that the grid is to take ownership
+        # of the table and will destroy it when done. Otherwise you
+        # would need to keep a reference to it and call it's Destroy
+        # method later.
+        self.SetTable(self.table, True)
+
+        #self.SetMargins(0,0)
+        self.AutoSizeColumn(0, True)
+
+        #self.SetSelectionMode(wxGrid.wxGridSelectRows)
+
+        #EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)
+        #EVT_GRID_SELECT_CELL(self, self.OnSelectCell)
+
+    def SetTableRecord(self, table, record):
+        self.table.SetTable(table, record)

Added: packages/thuban/branches/upstream/current/Thuban/UI/dbdialog.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/dbdialog.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/dbdialog.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,390 @@
+# Copyright (c) 2001, 2003, 2004 by Intevation GmbH
+# Authors:
+# Martin Mueller <mmueller at intevation.de>
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+
+"""Dialogs to manage database connections"""
+
+import sys, traceback
+
+import wx
+
+try:
+    import psycopg
+except ImportError:
+    psycopg = None
+
+from Thuban import _
+from Thuban.UI.dialogs import NonModalDialog
+from Thuban.Model.table import FIELDTYPE_INT
+from Thuban.Model.postgisdb import ConnectionError, PostGISConnection
+from Thuban.Model.messages import DBCONN_ADDED, DBCONN_REMOVED
+from messages import SESSION_REPLACED
+
+
+ID_DB_ADD    = 9101
+ID_DB_REMOVE = 9102
+
+ID_DBCHOOSE_RETRIEVE = 9201
+ID_DBCHOOSE_OK       = 9202
+ID_DBCHOOSE_CANCEL   = 9203
+ID_LB_DCLICK         = 9204
+
+
+class ChooseDBTableDialog(wx.Dialog):
+
+    def __init__(self, parent, session):
+        wx.Dialog.__init__(self, parent, -1, _("Choose layer from database"),
+                          style = wx.DIALOG_MODAL|wx.CAPTION)
+        self.session = session
+        self.dbconns = self.session.DBConnections()
+        self.tables = []
+
+        #
+        # Build the dialog
+        #
+
+        # Sizer for the entire dialog
+        top = wx.FlexGridSizer(2, 1, 0, 0)
+
+        # Sizer for the main part with the list boxes
+        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+        top.Add(main_sizer, 1, wx.EXPAND, 0)
+
+        # The list box with the connections
+        static_box = wx.StaticBoxSizer(wx.StaticBox(self, -1, _("Databases")),
+                                   wx.HORIZONTAL)
+        self.lb_connections = wx.ListBox(self, -1)
+        static_box.Add(self.lb_connections, 0, wx.EXPAND, 0)
+        main_sizer.Add(static_box, 1, wx.EXPAND, 0)
+
+        for i in range(len(self.dbconns)):
+            self.lb_connections.Append(self.dbconns[i].BriefDescription())
+        if self.lb_connections.GetCount() > 0:
+            self.lb_connections.SetSelection(0, True)
+
+        # The button box between the connections list box and the table
+        # list box
+        buttons = wx.FlexGridSizer(3, 1, 0, 0)
+        buttons.Add( (20, 80), 0, wx.EXPAND, 0)
+        retrieve_button = wx.Button(self, ID_DBCHOOSE_RETRIEVE, _("Retrieve"))
+        self.Bind(wx.EVT_BUTTON, self.OnRetrieve, id=ID_DBCHOOSE_RETRIEVE)
+        buttons.Add(retrieve_button, 0, wx.ALL
+                    |wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 4)
+        buttons.Add( (20, 80), 0, wx.EXPAND, 0)
+        main_sizer.Add(buttons, 0, wx.EXPAND, 0)
+
+        # The list box with the tables
+        static_box = wx.StaticBoxSizer(wx.StaticBox(self, -1, _("Tables")),
+                                   wx.HORIZONTAL)
+        self.lb_tables = wx.ListBox(self, ID_LB_DCLICK)
+        self.Bind(wx.EVT_LISTBOX, self.OnTableSelect, id=ID_LB_DCLICK)
+        self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnLBDClick, id=ID_LB_DCLICK)
+        static_box.Add(self.lb_tables, 0, wx.EXPAND, 0)
+        main_sizer.Add(static_box, 1, wx.EXPAND, 0)
+
+        # id column and geometry column selection
+        box = wx.BoxSizer(wx.VERTICAL)
+        box.Add(wx.StaticText(self, -1, _("ID Column")), 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.text_id_column = wx.ComboBox(self, -1, "")
+        box.Add(self.text_id_column, 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 4)
+
+        box.Add(wx.StaticText(self, -1, _("Geometry Column")), 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.text_geo_column = wx.ComboBox(self, -1, "")
+        box.Add(self.text_geo_column, 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 4)
+        main_sizer.Add(box, 1, wx.EXPAND, 0)
+
+        # The standard button box at the bottom of the dialog
+        buttons = wx.FlexGridSizer(1, 2, 0, 0)
+        ok_button = wx.Button(self, ID_DBCHOOSE_OK, _("OK"))
+        self.Bind(wx.EVT_BUTTON, self.OnOK, id=ID_DBCHOOSE_OK)
+        buttons.Add(ok_button, 0, wx.ALL|wx.ALIGN_RIGHT, 4)
+        cancel_button = wx.Button(self, ID_DBCHOOSE_CANCEL, _("Cancel"))
+        self.Bind(wx.EVT_BUTTON, self.OnCancel, id=ID_DBCHOOSE_CANCEL)
+        buttons.Add(cancel_button, 0, wx.ALL, 4)
+        top.Add(buttons, 1, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 4)
+
+        # Autosizing
+        self.SetAutoLayout(1)
+        self.SetSizer(top)
+        top.Fit(self)
+        top.SetSizeHints(self)
+        self.Layout()
+
+
+    def GetTable(self):
+        i = self.lb_tables.GetSelection()
+        if i >= 0:
+            return (self.selected_conn, self.tables[i],
+                    self.text_id_column.GetValue(),
+                    self.text_geo_column.GetValue())
+        return None
+
+    def OnRetrieve(self, event):
+        i = self.lb_connections.GetSelection()
+        if i >= 0:
+            self.selected_conn = self.dbconns[i]
+            self.tables = self.selected_conn.GeometryTables()
+            self.lb_tables.Set(self.tables)
+
+    def OnTableSelect(self, event):
+        i = self.lb_tables.GetSelection()
+        self.text_id_column.Clear()
+        self.text_geo_column.Clear()
+        if i >= 0:
+            for name, typ in self.selected_conn.table_columns(self.tables[i]):
+                if typ == "geometry":
+                    self.text_geo_column.Append(name)
+                elif typ == FIELDTYPE_INT:
+                    self.text_id_column.Append(name)
+
+    def OnLBDClick(self, event):
+        if self.lb_tables.GetSelection() >= 0:
+            self.EndModal(wx.ID_OK)
+            self.Show(False)
+
+    def OnOK(self, event):
+        self.EndModal(wx.ID_OK)
+        self.Show(False)
+
+    def OnCancel(self, event):
+        self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+
+class DBDialog(wx.Dialog):
+
+    """Dialog for the parameters of a database connection"""
+
+    def __init__(self, parent, title, parameters, message = ""):
+        """Initialize the dialog box.
+
+        The parameters argument should be a dictionary containing known
+        connection parameters.
+
+        The optional message parameter will be displayed at the top of
+        the dialog box and can be used to display error messages when
+        using the dialog to ask for correct parameters when the
+        connection can't be established.
+        """
+        wx.Dialog.__init__(self, parent, -1, title)
+
+        top = wx.BoxSizer(wx.VERTICAL)
+
+        if message:
+            top.Add(wx.StaticText(self, -1, message), 0,
+                    wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        box.Add(wx.StaticText(self, -1, _("Hostname:")), 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.text_host = wx.TextCtrl(self, -1, parameters.get("host", ""))
+        box.Add(self.text_host, 2, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 4)
+        box.Add(wx.StaticText(self, -1, _("Port:")), 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.text_port = wx.TextCtrl(self, -1, parameters.get("port", ""))
+        box.Add(self.text_port, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 4)
+        top.Add(box, 0, wx.EXPAND)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        box.Add(wx.StaticText(self, -1, _("Database Name:")), 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.text_dbname = wx.TextCtrl(self, -1,
+                                      parameters.get("dbname", ""))
+        box.Add(self.text_dbname, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 4)
+        top.Add(box, 0, wx.EXPAND)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        box.Add(wx.StaticText(self, -1, _("User:")), 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.text_user = wx.TextCtrl(self, -1,
+                                    parameters.get("user", ""))
+        box.Add(self.text_user, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 4)
+        box.Add(wx.StaticText(self, -1, _("Password:")), 0,
+                wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.text_password = wx.TextCtrl(self, -1,
+                                        parameters.get("password", ""),
+                                        style = wx.TE_PASSWORD)
+        box.Add(self.text_password, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND,
+                4)
+        top.Add(box, 0, wx.EXPAND)
+
+        buttons = wx.BoxSizer(wx.HORIZONTAL)
+        button = wx.Button(self, wx.ID_OK, _("OK"))
+        buttons.Add(button, 0, wx.ALL, 4)
+        button = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        buttons.Add(button, 0, wx.ALL, 4)
+        top.Add(buttons, 0, wx.ALIGN_RIGHT, 4)
+
+        self.SetAutoLayout(1)
+        self.SetSizer(top)
+        top.Fit(self)
+        top.SetSizeHints(self)
+
+        self.Bind(wx.EVT_BUTTON, self.OnOK, id=wx.ID_OK)
+        self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
+
+    def RunDialog(self):
+        self.ShowModal()
+        self.Destroy()
+        return self.result
+
+    def end_dialog(self, result):
+        self.result = result
+        if result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        result = {}
+        for name in ("host", "port", "dbname", "user", "password"):
+            result[name] = getattr(self, "text_" + name).GetValue()
+        self.end_dialog(result)
+
+    def OnCancel(self, event):
+        self.end_dialog(None)
+
+
+
+class DBFrame(NonModalDialog):
+
+    """Databse connection management dialog"""
+
+    def __init__(self, parent, name, session, *args, **kwds):
+        kwds["style"] = wx.ICONIZE|wx.CAPTION|wx.MINIMIZE
+        NonModalDialog.__init__(self, parent, name, "")
+        self.session = session
+        self.app = self.parent.application
+
+        self.app.Subscribe(SESSION_REPLACED, self.session_replaced)
+        self.subscribe_session()
+
+        self.DB_ListBox = wx.ListBox(self, -1,
+                              style=wx.LB_SINGLE|wx.LB_HSCROLL|wx.LB_ALWAYS_SB)
+        self.DB_Add = wx.Button(self, ID_DB_ADD, _("Add"))
+        self.DB_Remove = wx.Button(self, ID_DB_REMOVE, _("Remove"))
+        self.DB_CLOSE = wx.Button(self, wx.ID_CLOSE, _("Close"))
+        self.__set_properties()
+        self.__do_layout()
+        self.Bind(wx.EVT_BUTTON, self.OnAdd, id=ID_DB_ADD)
+        self.Bind(wx.EVT_BUTTON, self.OnRemove, id=ID_DB_REMOVE)
+        self.Bind(wx.EVT_BUTTON, self.OnClose, id=wx.ID_CLOSE)
+
+        self.conns_changed()
+
+    def __set_properties(self):
+        self.SetTitle(_("Database Management"))
+        self.DB_ListBox.SetSize((200, 157))
+
+    def __do_layout(self):
+        top = wx.BoxSizer(wx.VERTICAL)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+
+        box.Add(self.DB_ListBox, 1, wx.ALL|wx.EXPAND
+                |wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 4)
+
+        buttons = wx.BoxSizer(wx.VERTICAL)
+        buttons.Add(self.DB_Add, 0, wx.ALL, 4)
+        buttons.Add(self.DB_Remove, 0, wx.ALL, 4)
+
+        box.Add(buttons, 0, wx.EXPAND)
+        top.Add(box, 1, wx.EXPAND)
+
+        buttons = wx.BoxSizer(wx.HORIZONTAL)
+        buttons.Add(self.DB_CLOSE, 1, wx.ALL|wx.ALIGN_RIGHT, 4)
+        top.Add(buttons, 0, wx.ALIGN_RIGHT)
+
+        self.SetAutoLayout(1)
+        self.SetSizer(top)
+        top.Fit(self)
+        top.SetSizeHints(self)
+
+    def subscribe_session(self):
+        """Internal: Subscribe to some session messages"""
+        self.session.Subscribe(DBCONN_ADDED, self.conns_changed)
+        self.session.Subscribe(DBCONN_REMOVED, self.conns_changed)
+
+    def unsubscribe_session(self):
+        """Internal: Subscribe from messages subscribe in subscribe_session"""
+        self.session.Subscribe(DBCONN_ADDED, self.conns_changed)
+        self.session.Subscribe(DBCONN_REMOVED, self.conns_changed)
+
+    def session_replaced(self, *args):
+        """Internal: resubscribe the session messages
+
+        This method is a subscriber for the application's
+        SESSION_REPLACED messages.
+        """
+        self.unsubscribe_session()
+        self.session = self.app.Session()
+        self.subscribe_session()
+        self.conns_changed()
+
+    def conns_changed(self, *args):
+        """Internal: update the db connection list box
+
+        Subscribed to the DBCONN_ADDED and DBCONN_REMOVED messages.
+        """
+        self.DB_ListBox.Clear()
+        for conn in self.session.DBConnections():
+            self.DB_ListBox.Append(conn.BriefDescription(), conn)
+
+    def OnClose(self, event):
+        self.unsubscribe_session()
+        self.app.Unsubscribe(SESSION_REPLACED, self.session_replaced)
+        NonModalDialog.OnClose(self, event)
+
+    def RunMessageBox(self, title, text, flags = wx.OK | wx.ICON_INFORMATION):
+        """Run a modal message box with the given text, title and flags
+        and return the result"""
+        dlg = wxMessageDialog(self, text, title, flags)
+        dlg.CenterOnParent()
+        result = dlg.ShowModal()
+        dlg.Destroy()
+        return result
+
+    def OnAdd(self, event):
+        message = ""
+        parameters = {}
+        while 1:
+            dialog = DBDialog(self, _("Add Database"), parameters, message)
+            parameters = dialog.RunDialog()
+            if parameters is not None:
+                for conn in self.session.DBConnections():
+                    if conn.MatchesParameters(parameters):
+                        self.RunMessageBox(_("Add Database"),
+                                         _("Connection '%s' already exists")
+                                           % conn.BriefDescription())
+                        break
+                else:
+                    try:
+                        conn = PostGISConnection(**parameters)
+                    except ConnectionError, val:
+                        message = str(val)
+                    else:
+                        self.session.AddDBConnection(conn)
+                        break
+            else:
+                break
+
+    def OnRemove(self, event):
+        i = self.DB_ListBox.GetSelection()
+        if i >= 0:
+            conn = self.DB_ListBox.GetClientData(i)
+            if self.session.CanRemoveDBConnection(conn):
+                self.session.RemoveDBConnection(conn)
+            else:
+                self.RunMessageBox(_("Remove Database Connection"),
+                                   _("The connection %s\nis still in use")
+                                   % conn.BriefDescription())

Added: packages/thuban/branches/upstream/current/Thuban/UI/dialogs.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/dialogs.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/dialogs.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,70 @@
+# Copyright (c) 2001, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Base classes for dialogs"""
+
+__version__ = "$Revision: 2700 $"
+
+import wx
+
+class ThubanFrame(wx.Frame):
+
+    def __init__(self, parent, name, title):
+        wx.Frame.__init__(self, parent, -1, title,
+            style = wx.DEFAULT_FRAME_STYLE )
+        self.parent = parent
+        self.name = name
+        self.Bind(wx.EVT_CLOSE, self.OnClose)
+        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+
+    def OnClose(self, event):
+        # FIXME: Shouldn't this really be in OnDestroy?
+        if self.parent.dialogs.has_key(self.name):
+            self.parent.remove_dialog(self.name)
+        self.Destroy()
+
+    def OnDestroy(self, event):
+        """Implement in derived classes for resource cleanup, etc."""
+
+
+class NonModalDialog(wx.Dialog):
+    def __init__(self, parent, name, title):
+        wx.Dialog.__init__(self, parent, -1, title,
+            style = wx.DEFAULT_DIALOG_STYLE
+                  | wx.SYSTEM_MENU
+                  | wx.MINIMIZE_BOX
+                  | wx.MAXIMIZE_BOX
+                  | wx.RESIZE_BORDER
+            )
+        self.parent = parent
+        self.name = name
+        self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+    def OnClose(self, event):
+        if self.parent.dialogs.has_key(self.name):
+            self.parent.remove_dialog(self.name)
+        self.Destroy()
+
+class NonModalNonParentDialog(wx.Dialog):
+    def __init__(self, parent, name, title):
+        wx.Dialog.__init__(self, None, -1, title,
+            style = wx.DEFAULT_DIALOG_STYLE
+                  | wx.SYSTEM_MENU
+                  | wx.MINIMIZE_BOX
+                  | wx.MAXIMIZE_BOX
+                  | wx.RESIZE_BORDER
+                  | wx.DIALOG_NO_PARENT
+            )
+        self.parent = parent
+        self.name = name
+        self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+    def OnClose(self, event):
+        if self.parent.dialogs.has_key(self.name):
+            self.parent.remove_dialog(self.name)
+        self.Destroy()

Added: packages/thuban/branches/upstream/current/Thuban/UI/dock.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/dock.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/dock.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,511 @@
+# Copyright (c) 2003 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Classes for creating dockable windows.
+
+The DockFrame is the main window that will be the parent for the
+dockable windows.
+
+The DockPanel is a panel that all windows that wish to be dockable
+should derive from.
+"""
+
+__version__ = "$Revision: 2700 $"
+
+import resource
+
+from Thuban import _
+
+import wx
+
+from Thuban.Lib.connector import Publisher
+
+from dialogs import NonModalDialog
+
+from messages import DOCKABLE_DOCKED, DOCKABLE_UNDOCKED, DOCKABLE_CLOSED
+
+ID_BUTTON_DOCK = 4001
+ID_BUTTON_CLOSE = 4002
+
+PANEL_ID = 3141
+
+DOCK_BMP   = "dock_12"
+UNDOCK_BMP = "undock_12"
+CLOSE_BMP  = "close_12"
+
+class DockPanel(wx.Panel):
+    """A DockPanel is a panel that should be derived from to create panels
+    that can be docked in a DockFrame.
+    """
+
+    def __init__(self, parent, id):
+        """parent should be a DockableWindow created from 
+        DockFrame.CreateDock().
+        """
+
+        if not isinstance(parent, DockableWindow):
+            raise TypeError("")
+
+        wx.Panel.__init__(self, parent.GetCurrentParent(), id)
+
+        self.parent = parent
+
+        #self.SetDockParent(None)
+        #parent.SetPanel(self)
+
+    def Create(self):
+        self.parent.SetPanel(self)
+
+    def SetDockParent(self, parent):
+        self.__dockParent = parent
+
+    def GetDockParent(self):
+        return self.__dockParent
+
+    def SetDock(self, dock):
+        """Specifically set the docked state of the panel 
+        to dock (True or False).
+        """
+        #if dock == self.IsDocked(): return
+
+        if dock:
+            self.Dock()
+        else:
+            self.UnDock()
+
+    def Dock(self):
+        """Dock the panel in the DockFrame."""
+        self.GetDockParent().Dock()
+
+    def UnDock(self):
+        """Undock the panel in the DockFrame."""
+        self.GetDockParent().UnDock()
+
+    def IsDocked(self):
+        """Return True if the panel is docked."""
+        return self.GetDockParent().IsDocked()
+
+class DockableWindow(Publisher):
+
+    def __getattr__(self, attr):
+        return getattr(self.__topWindow, attr)
+
+    def __init__(self, parent, id, name, title, dockWindow, orient):
+        """Create the dockable window.
+
+        Initially, the window is hidden, but in an undocked state.
+        """
+
+        if not isinstance(parent, DockFrame): raise TypeError("")
+
+        self.__parent = parent
+        self.__id     = id
+        self.__name   = name
+
+        self.__orientation = orient
+
+        self.__dockWindow  = dockWindow
+        self.__floatWindow = wx.Frame(parent, id, title)
+
+        self.__docked      = False
+        if self.__docked:
+            self.__topWindow = self.__dockWindow
+        else:
+            self.__topWindow = self.__floatWindow
+
+        self.__floatSize     = None
+        self.__floatPosition = None
+
+        self.__dockPanel  = None
+        self.__panel = None
+
+        self.__dockWindow.Hide()
+        self.__floatWindow.Hide()
+
+        self.Bind(wx.EVT_CLOSE, self._OnClose)
+
+    ##
+    # Public methods
+    #
+
+    def GetName(self):
+        return self.__name
+
+    def SetPanel(self, panel):
+
+        if not isinstance(panel, DockPanel):
+            raise TypeError("")
+
+        self.__panel = panel
+        self.__panel.SetDockParent(self)
+        self.__CreateBorder()
+
+        self.SetDock(self.__docked)
+
+    def GetPanel(self):
+        return self.__panel
+
+    def GetCurrentParent(self):
+        return self.__topWindow
+
+    def SetDock(self, dock):
+
+        self.__CheckAllGood()
+
+        if dock:
+            self.Dock()
+        else:
+            self.UnDock()
+
+    def Dock(self):
+        """Dock the window."""
+        self.__CheckAllGood()
+
+        wasVisible = self.IsShown()
+
+        if wasVisible: self.Show(False)
+
+        self.__docked = True
+
+        #
+        # save window information
+        #
+        self.__floatSize = self.GetSize()
+        self.__floatPosition = self.GetPosition()
+
+        #
+        # reparent
+        #
+        self.__topWindow = self.__dockWindow
+        self.__dockPanel.Reparent(self.__topWindow)
+
+        self.__dockButton.SetBitmapLabel(self.__bmpUnDock)
+        self.__dockButton.SetBitmapFocus(self.__bmpUnDock)
+        self.__dockButton.SetBitmapSelected(self.__bmpUnDock)
+        self.__dockButton.SetBitmapDisabled(self.__bmpUnDock)
+        self.__dockButton.SetToolTip(wx.ToolTip(_("Undock")))
+
+        self.SetDockSize(self.__dockWindow.GetSize())
+
+        if wasVisible: self.Show(True)
+
+        self.issue(DOCKABLE_DOCKED, self.__id, self)
+
+    def UnDock(self):
+        """Undock the window."""
+        self.__CheckAllGood()
+
+        wasVisible = self.IsShown()
+
+        if wasVisible: self.Show(False)
+
+        self.__docked = False
+
+        #
+        # reparent
+        #
+        self.__topWindow = self.__floatWindow
+        self.__dockPanel.Reparent(self.__topWindow)
+
+        self.__dockButton.SetBitmapLabel(self.__bmpDock)
+        self.__dockButton.SetBitmapFocus(self.__bmpDock)
+        self.__dockButton.SetBitmapSelected(self.__bmpDock)
+        self.__dockButton.SetBitmapDisabled(self.__bmpDock)
+        self.__dockButton.SetToolTip(wx.ToolTip(_("Dock")))
+
+        if wasVisible: self.Show()
+
+        #
+        # restore window information
+        #
+        if self.__floatPosition is not None:
+            self.SetPosition(self.__floatPosition)
+        if self.__floatSize is not None:
+            self.SetSize(self.__floatSize)
+
+        self.__dockPanel.SetSize(self.__topWindow.GetClientSize())
+
+        self.issue(DOCKABLE_UNDOCKED, self.__id, self)
+
+    def IsDocked(self):
+        self.__CheckAllGood()
+        return self.__docked
+
+    def Show(self, show = True):
+        """Show or hide the window."""
+        if show:
+            self.__DoShow()
+        else:
+            self.__DoHide()
+
+    def SetDockSize(self, rect = None):
+        """Set the size of the dock window to rect."""
+
+        w0, h0 = self.__dockPanel.GetBestSize()
+        w, h = self.__panel.GetBestSize()
+
+        if (w, h) < (w0, h0):
+            w = w0
+            h = h0
+
+        if rect is not None:
+            rw = rect.width
+            rh = rect.height
+            if rw < w: rw = w
+            if rh < h: rh = h
+        else:
+            rw = w
+            rh = h
+
+        # these are to account for the border?!!?
+        rw += 8 # XXX: without this the sash isn't visible!?!?!?!
+        rh += 8 # XXX: without this the sash isn't visible!?!?!?!
+
+        self.__dockWindow.SetDefaultSize(wx.Size(rw, rh))
+
+
+    def Destroy(self):
+        self.__panel.Destroy()
+        self.__floatWindow.Destroy()
+        self.__dockWindow.Destroy()
+        self.__parent.OnDockDestroy(self)
+
+    ##
+    # Event handlers
+    #
+
+    def _OnButtonClose(self, event):
+        #self.Close()
+        self.Show(False)
+
+    def _OnClose(self, force = False):
+        self.Show(False)
+
+    def _OnToggleDock(self, event):
+        self.__CheckAllGood()
+
+        self.SetDock(not self.IsDocked())
+
+    ##
+    # Private methods
+    #
+
+    def __CheckAllGood(self):
+        if self.__panel is None:
+            raise TypeError("")
+
+    def __DoShow(self):
+        if self.IsShown(): return
+
+        self.__topWindow.Show()
+
+        if self.__topWindow is self.__dockWindow:
+            self.__parent._UpdateDocks()
+
+    def __DoHide(self):
+        if not self.IsShown(): return
+
+        self.__topWindow.Show(False)
+
+        if self.__topWindow is self.__dockWindow:
+            self.__parent._UpdateDocks()
+
+    def __CreateBorder(self):
+
+        self.__dockPanel = wx.Panel(self.__topWindow, -1, style=wx.SUNKEN_BORDER)
+
+        self.__panel.Reparent(self.__dockPanel)
+        self.__panel.SetId(PANEL_ID)
+
+        if self.__orientation == wx.LAYOUT_VERTICAL:
+            sizer = wx.BoxSizer(wx.VERTICAL)
+            headerBoxOrient = wx.HORIZONTAL
+        else:
+            sizer = wx.BoxSizer(wx.HORIZONTAL)
+            headerBoxOrient = wx.VERTICAL
+
+
+        headerBox = wx.StaticBoxSizer(
+                        wx.StaticBox(self.__dockPanel, -1, ""), headerBoxOrient)
+
+        #
+        # ideally, we should be able to rotate this text depending on
+        # our orientation
+        #
+        text = wx.StaticText(self.__dockPanel, -1, self.GetTitle(),
+                             style = wx.ALIGN_CENTRE)
+        font = text.GetFont()
+        font.SetPointSize(10)
+        text.SetFont(font)
+
+        #
+        # load the dock/undock/close bitmaps
+        # and create the buttons
+        #
+        self.__bmpDock   = \
+            resource.GetBitmapResource(DOCK_BMP, wx.BITMAP_TYPE_XPM)
+        self.__bmpUnDock = \
+            resource.GetBitmapResource(UNDOCK_BMP, wx.BITMAP_TYPE_XPM)
+
+        if self.__docked:
+            bmp = self.__bmpDock
+        else:
+            bmp = self.__bmpUnDock
+
+        self.__dockButton = wx.BitmapButton(
+            self.__dockPanel, ID_BUTTON_DOCK,
+            bmp,
+            size = wx.Size(bmp.GetWidth() + 4, bmp.GetHeight() + 4),
+            style = wx.BU_EXACTFIT | wx.ADJUST_MINSIZE)
+
+        bmp = resource.GetBitmapResource(CLOSE_BMP, wx.BITMAP_TYPE_XPM)
+
+        closeX = wx.BitmapButton(self.__dockPanel, ID_BUTTON_CLOSE, bmp,
+                          size = wx.Size(bmp.GetWidth() + 4,
+                                        bmp.GetHeight() + 4),
+                          style = wx.BU_EXACTFIT | wx.ADJUST_MINSIZE)
+        closeX.SetToolTip(wx.ToolTip(_("Close")))
+
+        #
+        # fill in the sizer in an order appropriate to the orientation
+        #
+        if self.__orientation == wx.LAYOUT_VERTICAL:
+            headerBox.Add(text, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTRE_VERTICAL, 0)
+            headerBox.Add((1, 5), 1, wx.GROW)
+            headerBox.Add(self.__dockButton, 0, wx.ALIGN_RIGHT, 0)
+            headerBox.Add(closeX, 0, wx.ALIGN_RIGHT | wx.LEFT, 4)
+        else:
+            headerBox.Add(closeX, 0, wx.ALIGN_RIGHT | wx.BOTTOM, 4)
+            headerBox.Add(self.__dockButton, 0, wx.ALIGN_RIGHT, 0)
+            headerBox.Add(text, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTRE_VERTICAL, 0)
+
+        sizer.Add(headerBox, 0, wx.GROW, 0)
+        sizer.Add(self.__panel, 1, wx.GROW, 0)
+
+
+        self.__dockPanel.SetAutoLayout(True)
+        self.__dockPanel.SetSizer(sizer)
+        sizer.SetSizeHints(self.__dockPanel)
+        sizer.SetSizeHints(self.__floatWindow)
+
+        self.Bind(wx.EVT_BUTTON, self._OnToggleDock, self.__dockPanel, id=ID_BUTTON_DOCK)
+        self.Bind(wx.EVT_BUTTON, self._OnButtonClose, self.__dockPanel, id=ID_BUTTON_CLOSE)
+
+
+class DockFrame(wx.Frame):
+    """A DockFrame is a frame that will contain dockable panels."""
+
+    def __init__(self, parent, id, title, position, size):
+        wx.Frame.__init__(self, parent, id, title, position, size)
+
+        self.openWindows = {}
+
+        self.__update_lock = 0
+
+        self.SetMainWindow(None)
+
+
+        self.Bind(wx.EVT_SIZE, self._OnSashSize)
+        self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+    layout2oppSash = {
+            wx.LAYOUT_NONE   : wx.SASH_NONE,
+            wx.LAYOUT_TOP    : wx.SASH_BOTTOM,
+            wx.LAYOUT_LEFT   : wx.SASH_RIGHT,
+            wx.LAYOUT_RIGHT  : wx.SASH_LEFT,
+            wx.LAYOUT_BOTTOM : wx.SASH_TOP }
+
+
+    def OnClose(self, event):
+
+        self.__update_lock += 1
+
+        #
+        # child windows are not notified when the parent is destroyed
+        # as of v2.4.0.3 so we need to interate over our children
+        # and tell them to go away.
+        #
+        for key in self.openWindows.keys():
+            win = self.openWindows[key]
+            win.Destroy()
+
+        self.__update_lock -= 1
+
+        # should really call _UpdateDocks() here but we don't need to
+        # since we're going away
+
+    def CreateDock(self, name, id, title, align):
+        """Create a new dock. align specifies where the dock will
+        be placed. It can be one of wxLAYOUT_NONE, wxLAYOUT_LEFT, 
+        wxLAYOUT_RIGHT.
+        """
+
+        if align in (wx.LAYOUT_NONE, wx.LAYOUT_LEFT, wx.LAYOUT_RIGHT):
+            orient = wx.LAYOUT_VERTICAL
+        else:
+            orient = wx.LAYOUT_HORIZONTAL
+
+        sash = wx.SashLayoutWindow(self, id, style=wx.NO_BORDER|wx.SW_3D)
+        sash.SetOrientation(orient)
+        sash.SetAlignment(align)
+        sash.SetSashVisible(DockFrame.layout2oppSash[align], True)
+        sash.SetSashBorder(DockFrame.layout2oppSash[align], True)
+
+        win = DockableWindow(self, id, name, title, sash, orient)
+
+        self.__RegisterDock(name, win)
+        self.Bind(wx.EVT_SASH_DRAGGED, self._OnSashDragged, id=id)
+
+        return win
+
+    def FindRegisteredDock(self, name):
+        """Return a reference to a dock that has name."""
+        return self.openWindows.get(name)
+
+    def OnDockDestroy(self, win):
+        del self.openWindows[win.GetName()]
+        self._UpdateDocks()
+
+    def SetMainWindow(self, main):
+        self.__mainWindow = main
+        self._UpdateDocks()
+
+    def _UpdateDocks(self):
+        if self.__update_lock == 0:
+            wx.LayoutAlgorithm().LayoutWindow(self, self.__mainWindow)
+
+    def _OnSashDragged(self, event):
+        if event.GetDragStatus() == wx.SASH_STATUS_OUT_OF_RANGE:
+            return
+
+        id = event.GetId()
+        sash = self.FindWindowById(id)
+        #assert(isinstance(win, wxPanel))
+        dockPanel = sash.GetChildren()[0]
+        panel = dockPanel.FindWindowById(PANEL_ID)
+        assert isinstance(panel, DockPanel)
+        win = panel.GetDockParent()
+        assert isinstance(win, DockableWindow)
+
+        assert win.IsDocked()
+
+        rect = event.GetDragRect()
+
+        win.SetDockSize(rect)
+
+        self._UpdateDocks()
+
+    def _OnSashSize(self, event):
+        self._UpdateDocks()
+
+    def __RegisterDock(self, name, win):
+        if self.FindRegisteredDock(name) is not None:
+            raise ValueError(
+                "A dockable window is already registered under the name '%s'" % name)
+
+        self.openWindows[name] = win
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/exceptiondialog.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/exceptiondialog.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/exceptiondialog.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,64 @@
+# Copyright (c) 2003 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagnber <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2700 $"
+
+import sys
+
+import wx
+
+from Thuban import _
+
+class ExceptionDialog(wx.Dialog):
+
+    """The exception dialog shows the exception message and then allows
+    to either proceed with the application or to exit it. In the
+    latter case, sys.exit(1) is applied immediately.
+    """
+
+    def __init__(self, parent, message, title = _('Thuban: Internal Error')):
+        wx.Dialog.__init__(self, parent, -1, title,
+                          wx.DefaultPosition,
+                          style = wx.RESIZE_BORDER|wx.CAPTION|wx.DIALOG_MODAL)
+
+        self.parent = parent
+        self.dialog_layout(message)
+
+    def dialog_layout(self, message):
+        top_box = wx.BoxSizer(wx.VERTICAL)
+
+        textBox = wx.TextCtrl(self, -1, message,
+            style=wx.TE_READONLY|wx.TE_MULTILINE|wx.TE_LINEWRAP)
+        w, h = (500, 300)
+        textBox.SetSizeHints(w, h)
+        textBox.SetSize((w, h))
+
+        top_box.Add(textBox, 1, wx.EXPAND|wx.ALL, 10)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        box.Add(wx.Button(self, wx.ID_OK, _("Proceed")), 0, wx.ALL, 4)
+        box.Add(wx.Button(self, wx.ID_CANCEL, _("Exit Thuban now")), 0, wx.ALL, 4)
+        top_box.Add(box, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 10)
+
+        self.Bind(wx.EVT_BUTTON, self.OnOK, id=wx.ID_OK)
+        self.Bind(wx.EVT_BUTTON, self.OnExit, id=wx.ID_CANCEL)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(top_box)
+        top_box.Fit(self)
+        top_box.SetSizeHints(self)
+
+    def OnOK(self, event):
+        self.EndModal(wx.ID_OK)
+
+    def OnExit(self, event):
+        sys.exit(1)
+
+def run_exception_dialog(parent, message, title = _('Thuban: Internal Error')):
+    dialog = ExceptionDialog(parent, message, title)
+    dialog.ShowModal()
+    dialog.Destroy()

Added: packages/thuban/branches/upstream/current/Thuban/UI/extensionregistry.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/extensionregistry.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/extensionregistry.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,116 @@
+# Copyright (C) 2004, 2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de> (2004, 2005)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Registry for Extensions.
+
+This module defines a registry for Extensions.
+This is basically used for displaying information on
+the active Extensions in the general About-Dialog.
+A registration is not mandatory to make a Extension
+work, but any Extension should register to provide
+a complete information in the Thuban About Dialog.
+
+A Extension should define a ExtensionDesc object
+and apply ext_registry.add() to register it.
+"""
+
+__version__ = "$Revision: 2580 $"
+# $Source$
+# $Id: extensionregistry.py 2580 2005-03-10 22:39:11Z jan $
+
+from Thuban import _
+
+class ExtensionDesc:
+
+    """
+    A description of a Thuban Extension.
+    """
+
+    def __init__(self, name, version, authors, copyright, desc,
+                 init_callback = None):
+        """
+        Initialize a new Thuban Extension information.
+
+        name -- The name of the Thuban Extension.
+                Example: 'gns2shp'
+
+        version -- The version number of the Thuban Extension.
+                   Example: '1.0.0'
+
+        authors -- List of authors.
+                   Example: [ 'Jan-Oliver Wagner' ]
+
+        copyright -- Copyright notice.
+                     Example: '2003, 2004 Intevation GmbH'
+
+        desc -- Short description of the Thuban Extension.
+                Example: _('''
+                         Converts GNS (Geographical Name Service of NIMA)
+                         to Shapefile format and displays the data.
+                         ''')
+        init_callback -- a callback method that is executed if not
+                         None. This method should contain gui specific
+                         initializations of the extension.
+                         Default is None.
+
+                         This callback should return None if
+                         the intialisation as successful. Else
+                         a string describing the problems during
+                         intialization.
+        """
+        self.name = name
+        self.version = version
+        self.authors = authors
+        self.copyright = copyright
+        self.desc = desc
+        self.init_callback = init_callback
+        self.status = _("Initialization not yet requested.")
+
+    def init_ext(self):
+        """Execute the init callback for the extension.
+
+        Do nothing if the callback is None.
+
+        It is expected that the callback function returns
+        None if all was OK and a string if something was wrong.
+        The string is believed to describe the problems.
+        """
+        if self.init_callback is not None:
+            result = self.init_callback()
+            if result is not None:
+                self.status = result
+            else:
+                self.status = _("Initialization successful.")
+
+class ExtensionRegistry:
+
+    """
+    A ExtensionRegistry keeps information on the registered
+    Thuban Extensions.
+
+    The registry will raise a exception either when the version
+    required for the Extensions exceeds the version of the currently
+    running Thuban or if the name of a registered extension already
+    is used for registering another extension.
+    """
+
+    def __init__(self):
+        self.registry = []
+
+    def __nonzero__(self):
+        return len(self.registry) <> 0
+
+    def __iter__(self):
+        return iter(self.registry)
+
+    def add(self, ext):
+        self.registry.append(ext)
+
+
+# The central Thuban Extensions registry
+ext_registry = ExtensionRegistry()

Added: packages/thuban/branches/upstream/current/Thuban/UI/hittest.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/hittest.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/hittest.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,88 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Martin Mueller <mmueller at intevation.de>
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Hit testing functions"""
+
+__version__ = "$Revision: 1589 $"
+# $Source$
+# $Id: hittest.py 1589 2003-08-15 12:49:08Z bh $
+
+from math import hypot, sqrt
+
+def line_hit(sx, sy, ex, ey, px, py):
+    """Determine whether the line fom (SX, SY) to (EX, EY) is `hit' by a
+    click at (PX, PY), or whether a polygon containing this line is hit
+    in the interior at (PX, PY).
+
+    Return -1 if the line it self his hit. Otherwise, return +1 if a
+    horizontal line from (PX, PY) to (-Infinity, PY) intersects the line
+    and 0 if it doesn't.
+
+    The nonnegative return values can be used to determine whether (PX, PY)
+    is an interior point of a polygon according to the even-odd rule.
+    """
+
+    if (ey < sy):
+        sx, ex = ex, sx
+        sy, ey = ey, sy
+
+    not_horizontal = ey > sy + 2
+    if not_horizontal and (py >= ey or py < sy):
+        return 0
+
+    vx = ex - sx
+    vy = ey - sy
+
+    len = sqrt(vx * vx + vy * vy)
+    if not len:
+        # degenerate case of coincident end points. Assumes that some
+        # other part of the code has already determined whether the end
+        # point is hit.
+        return 0
+
+    dx = px - sx
+    dy = py - sy
+    dist = vx * dy - vy * dx
+
+    if ((not_horizontal or (px >= sx and px <= ex) or (px >= ex and px <= sx))
+        and abs(dist) <= (len * 2)):
+        return -1
+
+    # horizontal lines (vy == 0) always return 0 here.
+    return vy and py < ey and py >= sy and dx * abs(vy) > vx * abs(dy)
+
+
+def polygon_hit(points, x, y):
+    """Return whether x, y is in the polygon or on or near the boundary
+
+    The return value is -1 if the point (x, y) is near the boundary, 1
+    if the point is inside and 0 if it's outside.
+
+    The points argument should be a list of lists of coordinate pairs.
+    """
+    crossings = 0
+    for ring in points:
+        for i in range(len(ring) - 1):
+            sx, sy = ring[i]
+            ex, ey = ring[i + 1]
+            hit = line_hit(sx, sy, ex, ey, x, y)
+            if hit < 0:
+                return hit
+            crossings += hit
+    return crossings % 2
+
+
+def arc_hit(points, x, y):
+    """Return whether x, y is on or near the arc's boundary
+
+    The return value is -1 if the point (x, y) is near the boundary, 1
+    if the point is inside and 0 if it's outside.
+
+    The points argument should be a list of lists of coordinate pairs.
+    """
+    return polygon_hit(points, x, y) < 0

Added: packages/thuban/branches/upstream/current/Thuban/UI/identifyview.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/identifyview.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/identifyview.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,92 @@
+# Copyright (c) 2001, 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2700 $"
+
+import wx
+from wx import grid
+
+from Thuban import _
+
+from dialogs import NonModalDialog
+from controls import RecordListCtrl, RecordGridCtrl
+from messages import SHAPES_SELECTED
+import main
+
+class IdentifyListCtrl(RecordListCtrl):
+
+    def selected_shape(self, layer, shape):
+        if layer is not None:
+            table = layer.ShapeStore().Table()
+        else:
+            table = None
+        self.fill_list(table, shape)
+
+class IdentifyGridCtrl(RecordGridCtrl):
+
+    def selected_shape(self, layer, shape):
+        if layer is not None:
+            table = layer.ShapeStore().Table()
+        else:
+            table = None
+        self.SetTableRecord(table, shape)
+
+class IdentifyView(NonModalDialog):
+
+    ID_STOP = 100
+
+    def __init__(self, parent, name):
+        NonModalDialog.__init__(self, parent, name, _("Identify Shape"))
+        parent.Subscribe(SHAPES_SELECTED, self.selected_shape)
+
+        top_box = wx.BoxSizer(wx.VERTICAL)
+        if main.options.attribute_editing_enabled:
+            self.list = IdentifyGridCtrl(self)
+        else:
+            self.list = IdentifyListCtrl(self, -1)
+        self.list.SetSize(wx.Size(305,200))
+        top_box.Add(self.list, 1, wx.EXPAND|wx.ALL, 4)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        box.Add(wx.Button(self, wx.ID_CLOSE, _("Close Window")), 0, wx.ALL, 4)
+        box.Add(wx.Button(self, self.ID_STOP, _("Stop Identify Mode")),
+                         0, wx.ALL, 4)
+        top_box.Add(box, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 4)
+
+        self.Bind(wx.EVT_BUTTON, self.OnClose, id=wx.ID_CLOSE)
+        self.Bind(wx.EVT_BUTTON, self.OnStop, id=self.ID_STOP)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(top_box)
+        top_box.Fit(self)
+        top_box.SetSizeHints(self)
+
+        # Make sure to reflect the current selection.
+        self.selected_shape(parent.SelectedLayer(), parent.SelectedShapes())
+
+    def OnClose(self, event):
+        self.parent.Unsubscribe(SHAPES_SELECTED, self.selected_shape)
+        NonModalDialog.OnClose(self, event)
+
+    def OnStop(self, event):
+        self.parent.Unsubscribe(SHAPES_SELECTED, self.selected_shape)
+        self.parent.canvas.SelectTool(None)
+        NonModalDialog.OnClose(self, event)
+
+    def selected_shape(self, layer, shapes):
+        """Subscribed to the SHAPES_SELECTED messages.
+
+        If exactly one shape is selected, pass that shape id to the
+        list's selected_shape method. Otherwise pass None as the shape
+        id.
+        """
+        if len(shapes) == 1:
+            shape = shapes[0]
+        else:
+            shape = None
+        self.list.selected_shape(layer, shape)

Added: packages/thuban/branches/upstream/current/Thuban/UI/join.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/join.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/join.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,246 @@
+# Copyright (c) 2003 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""The layer and table join dialog"""
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: join.py 2700 2006-09-18 14:27:02Z dpinte $
+
+
+import sys
+import wx
+
+from Thuban import _
+
+from Thuban.Model.transientdb import TransientJoinedTable
+from Thuban.Model.data import DerivedShapeStore
+from Thuban.UI.tableview import QueryTableFrame
+
+from common import ThubanBeginBusyCursor, ThubanEndBusyCursor
+
+ID_LEFT_TABLE = 4001
+ID_RIGHT_TABLE = 4002
+
+CHOICE_WIDTH = 150
+
+class JoinDialog(wx.Dialog):
+
+    """Table join dialog.
+
+    Join two tables (left/right) based on the user selected fields.
+    Opens a QueryTableFrame and registers the new table with the session.
+    """
+
+    def __init__(self, parent, title, session, layer = None):
+        wx.Dialog.__init__(self, parent, -1, title,
+                          style = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
+        self.layer = layer
+
+        if not layer:
+            self.choice_left_table = wx.Choice(self, ID_LEFT_TABLE)
+            width, height = self.choice_left_table.GetSizeTuple()
+            self.choice_left_table.SetSize(wx.Size(CHOICE_WIDTH, height))
+            self.left_table = None
+        else:
+            self.choice_left_table = None
+            self.left_table = layer.ShapeStore().Table()
+
+        self.choice_right_table = wx.Choice(self, ID_RIGHT_TABLE)
+        width, height = self.choice_right_table.GetSizeTuple()
+        self.choice_right_table.SetSize(wx.Size(CHOICE_WIDTH, height))
+
+        self.choice_left_field = wx.Choice(self, -1)
+        width, height = self.choice_left_field.GetSizeTuple()
+        self.choice_left_field.SetSize(wx.Size(CHOICE_WIDTH, height))
+        self.choice_right_field = wx.Choice(self, -1)
+        width, height = self.choice_right_field.GetSizeTuple()
+        self.choice_right_field.SetSize(wx.Size(CHOICE_WIDTH, height))
+
+        self.button_join = wx.Button(self, wx.ID_OK, _("Join"))
+        self.button_join.SetDefault()
+        self.button_close = wx.Button(self, wx.ID_CANCEL, _("Close"))
+
+        self.Bind(wx.EVT_BUTTON, self.OnJoin, id=wx.ID_OK)
+
+        if self.choice_left_table is not None:
+            self.choice_left_table.Append(_('Select...'), None)
+        self.choice_right_table.Append(_('Select...'), None)
+
+        for t in session.Tables():
+            if self.choice_left_table is not None:
+                self.choice_left_table.Append(t.Title(), t)
+
+            # If there is no choice_left_table then self.left_table will
+            # be the keft table so we can simply leave it out on the
+            # right side.
+            if t is not self.left_table:
+                self.choice_right_table.Append(t.Title(), t)
+
+        if self.choice_left_table is None:
+            for col in self.left_table.Columns():
+                self.choice_left_field.Append(col.name, col)
+
+        if self.choice_left_table is not None:
+            self.Bind(wx.EVT_CHOICE, self.OnLeftTable, id=ID_LEFT_TABLE)
+        self.Bind(wx.EVT_CHOICE, self.OnRightTable, id=ID_RIGHT_TABLE)
+
+        if self.choice_left_table is not None:
+            self.choice_left_table.SetSelection(0)
+        self.choice_right_table.SetSelection(0)
+        self.button_join.Enable(False)
+
+        topBox = wx.BoxSizer(wx.VERTICAL)
+
+        sizer = wx.FlexGridSizer(2, 4)
+        sizer.Add(wx.StaticText(self, -1, _("Table:")), 0, wx.ALL, 4)
+        if self.choice_left_table is not None:
+            sizer.Add(self.choice_left_table, 1,
+                      wx.EXPAND|wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        else:
+            sizer.Add(wx.StaticText(self, -1, self.left_table.Title()), 0,
+                      wx.ALL, 4)
+
+        sizer.Add(wx.StaticText(self, -1, _("Table:")), 0, wx.ALL, 4)
+        sizer.Add(self.choice_right_table, 1,
+                  wx.EXPAND|wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        sizer.Add(wx.StaticText(self, -1, _("Field:")), 0, wx.ALL, 4)
+        sizer.Add(self.choice_left_field, 1,
+                  wx.EXPAND|wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        sizer.Add(wx.StaticText(self, -1, _("Field:")), 0, wx.ALL, 4)
+        sizer.Add(self.choice_right_field, 1,
+                  wx.EXPAND|wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+
+        sizer.AddGrowableCol(1)
+        sizer.AddGrowableCol(3)
+
+        topBox.Add(sizer, 0, wx.EXPAND|wx.ALL, 4)
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        self.check_outer_join = wx.CheckBox(self,-1,
+                                _("Outer Join (preserves left table records)"))
+        sizer.Add(self.check_outer_join, 1, wx.ALL,4)
+        topBox.Add(sizer, 0, wx.ALIGN_LEFT|wx.ALIGN_TOP, 4)
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        sizer.Add(self.button_join, 0, wx.ALIGN_RIGHT|wx.ALIGN_BOTTOM|wx.RIGHT,
+                  10)
+        sizer.Add(self.button_close, 0, wx.ALIGN_RIGHT|wx.ALIGN_BOTTOM|wx.RIGHT,
+                  10)
+
+        topBox.Add(sizer, 1, wx.ALIGN_RIGHT|wx.ALIGN_BOTTOM|wx.BOTTOM|wx.TOP, 10)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(topBox)
+        topBox.Fit(self)
+        topBox.SetSizeHints(self)
+
+        # Save same parameters for later use.
+        self.parent = parent
+        self.session = session
+
+    def OnJoin(self, event):
+        """Get the table and field selections and perform the join."""
+        ThubanBeginBusyCursor()
+        try:
+            # left
+            if self.choice_left_table is not None:
+                i = self.choice_left_table.GetSelection()
+                left_table = self.choice_left_table.GetClientData(i)
+            else:
+                left_table = self.left_table
+            i = self.choice_left_field.GetSelection()
+            left_field  = self.choice_left_field.GetString(i)
+            # right
+            i = self.choice_right_table.GetSelection()
+            right_table = self.choice_right_table.GetClientData(i)
+            i = self.choice_right_field.GetSelection()
+            right_field  = self.choice_right_field.GetString(i)
+
+            outer_join = self.check_outer_join.IsChecked()
+
+            try:
+                joined_table = TransientJoinedTable(self.session.TransientDB(),
+                                                    left_table, left_field,
+                                                    right_table, right_field,
+                                                    outer_join)
+            except:
+                dlg = wx.MessageDialog(None,
+                                      _('Join failed:\n  %s') % sys.exc_info()[1],
+                                      _('Info'), wx.OK|wx.ICON_ERROR)
+                dlg.ShowModal()
+                dlg.Destroy()
+                return
+
+            joined_table = self.session.AddTable(joined_table)
+
+            if self.layer is not None:
+                needed_rows = self.layer.ShapeStore().Table().NumRows()
+                joined_rows = joined_table.NumRows()
+                if needed_rows == joined_rows:
+                    store = DerivedShapeStore(self.layer.ShapeStore(),
+                                          joined_table)
+                    self.session.AddShapeStore(store)
+                    self.layer.SetShapeStore(store)
+
+        finally:
+            ThubanEndBusyCursor()
+
+        if self.layer is not None:
+            if needed_rows != joined_rows:
+                msg = _("The joined table has %(joined)d rows but"
+                        " it must have %(needed)d rows"
+                        " to be used with the selected layer") \
+                        % {"joined": joined_rows,
+                           "needed": needed_rows}
+                dlg = wx.MessageDialog(None, msg, _('Join Failed'),
+                                      wx.OK|wx.ICON_ERROR)
+                dlg.ShowModal()
+                dlg.Destroy()
+                return
+
+        else:
+            name = joined_table.tablename
+            dialog = QueryTableFrame(self.parent, name,
+                                     _('Table: %s') % joined_table.Title(),
+                                     joined_table)
+            self.parent.add_dialog(name, dialog)
+            dialog.Show(True)
+
+        self.Close()
+
+    def OnClose(self, event):
+        """Close the dialog."""
+        self.Close()
+
+    def OnLeftTable(self, event):
+        """Get the selected table and fill the field choice."""
+        i = self.choice_left_table.GetSelection()
+        table = self.choice_left_table.GetClientData(i)
+        self.choice_left_field.Clear()
+        if table is not None:
+            for col in table.Columns():
+                self.choice_left_field.Append(col.name, col)
+        self.update_sensitivity()
+
+    def OnRightTable(self, event):
+        """Get the selected table and fill the field choice."""
+        i = self.choice_right_table.GetSelection()
+        table = self.choice_right_table.GetClientData(i)
+        self.choice_right_field.Clear()
+        if table is not None:
+            for col in table.Columns():
+                self.choice_right_field.Append(col.name, col)
+        self.update_sensitivity()
+
+    def update_sensitivity(self):
+        if self.choice_left_table is not None:
+            lsel = self.choice_left_table.GetSelection()
+        else:
+            lsel = sys.maxint
+        sel = self.choice_right_table.GetSelection()
+        self.button_join.Enable(sel > 0 and lsel > 0 and sel != lsel)

Added: packages/thuban/branches/upstream/current/Thuban/UI/labeldialog.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/labeldialog.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/labeldialog.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,73 @@
+# Copyright (c) 2001 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2700 $"
+
+import wx
+
+from Thuban import _
+
+from controls import SelectableRecordListCtrl
+
+class LabelListCtrl(SelectableRecordListCtrl):
+
+    def __init__(self, parent, id, table, shape):
+        SelectableRecordListCtrl.__init__(self, parent, id)
+        self.fill_list(table, shape)
+
+
+class LabelDialog(wx.Dialog):
+
+    def __init__(self, parent, table, shape_index):
+        wx.Dialog.__init__(self, parent, -1, _("Label Values"),
+                          wx.DefaultPosition,
+                          style = wx.RESIZE_BORDER|wx.CAPTION|wx.DIALOG_MODAL)
+
+        self.parent = parent
+        self.dialog_layout(table, shape_index)
+
+    def dialog_layout(self, table, shape_index):
+        top_box = wx.BoxSizer(wx.VERTICAL)
+
+        self.list = LabelListCtrl(self, -1, table, shape_index)
+        self.list.SetSize(wx.Size(305,200))
+        top_box.Add(self.list, 1, wx.EXPAND|wx.ALL, 4)
+
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        box.Add(wx.Button(self, wx.ID_OK, _("OK")), 0, wx.ALL, 4)
+        box.Add(wx.Button(self, wx.ID_CANCEL, _("Cancel")), 0, wx.ALL, 4)
+        top_box.Add(box, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 10)
+
+        self.Bind(wx.EVT_BUTTON, self.OnOK, id=wx.ID_OK)
+        self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(top_box)
+        top_box.Fit(self)
+        top_box.SetSizeHints(self)
+
+    def OnOK(self, event):
+        result = self.list.GetValue()
+        if result is not None:
+            self.end_dialog(wx.ID_OK, str(result))
+        else:
+            self.end_dialog(wx.ID_CANCEL, None)
+
+    def OnCancel(self, event):
+        self.end_dialog(wx.ID_CANCEL, None)
+
+    def end_dialog(self, wx_result, result):
+        self.result = result
+        self.EndModal(wx_result)
+
+def run_label_dialog(parent, table, shape_index):
+    dialog = LabelDialog(parent, table, shape_index)
+    if dialog.ShowModal() == wx.ID_OK:
+        return dialog.result
+    else:
+        return None
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/layerproperties.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/layerproperties.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/layerproperties.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,168 @@
+# Copyright (c) 2005 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de> 
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Base class for Layer Properties dialogs"""
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: layerproperties.py 2700 2006-09-18 14:27:02Z dpinte $
+
+from Thuban import _
+
+import wx
+from Thuban.Model.messages import MAP_LAYERS_REMOVED, LAYER_SHAPESTORE_REPLACED
+from dialogs import NonModalNonParentDialog
+from messages import MAP_REPLACED
+
+ID_PROPERTY_REVERT = 4002
+ID_PROPERTY_TRY = 4008
+ID_PROPERTY_TITLE = 4012
+
+class LayerProperties(NonModalNonParentDialog):
+
+    def __init__(self, parent, name, layer):
+
+        NonModalNonParentDialog.__init__(self, parent, name, "")
+
+        self.SetTitle(layer.Title())
+
+        self.parent.Subscribe(MAP_REPLACED, self.map_replaced)
+        self.layer = layer
+        self.map = parent.Map()
+
+        self.map.Subscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)
+
+        self.layout_recurse = False
+
+    def dialog_layout(self, *args, **kw):
+
+        if self.layout_recurse: return
+        self.layout_recurse = True
+
+        panel = wx.Panel(self, -1)
+
+        topBox = wx.BoxSizer(wx.VERTICAL)
+        panelBox = wx.BoxSizer(wx.VERTICAL)
+
+        # Title
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        sizer.Add(wx.StaticText(panel, -1, _("Title: ")),
+            0, wx.ALIGN_LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 4)
+
+        text_title = wx.TextCtrl(panel, ID_PROPERTY_TITLE, self.layer.Title())
+        text_title.SetInsertionPointEnd()
+        sizer.Add(text_title, 1, wx.GROW | wx.RIGHT, 0)
+
+        panelBox.Add(sizer, 0, wx.GROW | wx.ALL, 4)
+
+        # Type
+        panelBox.Add(wx.StaticText(panel, -1,
+            _("Layer Type: %s") % self.layer.Type()),
+            0, wx.ALIGN_LEFT | wx.ALL, 4)
+
+        # Projection
+        proj = self.layer.GetProjection()
+        if proj is None:
+            text = _("Projection: None")
+        else:
+            text = _("Projection: %s") % proj.Label()
+
+        panelBox.Add(wx.StaticText(panel, -1, text), 0, wx.ALIGN_LEFT | wx.ALL, 4)
+
+        self.dialog_layout(panel, panelBox)
+
+        button_try = wx.Button(self, ID_PROPERTY_TRY, _("Try"))
+        button_revert = wx.Button(self, ID_PROPERTY_REVERT, _("Revert"))
+        button_ok = wx.Button(self, wx.ID_OK, _("OK"))
+        button_close = wx.Button(self, wx.ID_CANCEL, _("Close"))
+        button_ok.SetDefault()
+
+        buttonBox = wx.BoxSizer(wx.HORIZONTAL)
+        buttonBox.Add(button_try, 0, wx.RIGHT|wx.EXPAND, 10)
+        buttonBox.Add(button_revert, 0, wx.RIGHT|wx.EXPAND, 10)
+        buttonBox.Add(button_ok, 0, wx.RIGHT|wx.EXPAND, 10)
+        buttonBox.Add(button_close, 0, wx.RIGHT|wx.EXPAND, 0)
+
+        panel.SetAutoLayout(True)
+        panel.SetSizer(panelBox)
+        panelBox.Fit(panel)
+        panelBox.SetSizeHints(panel)
+
+        topBox.Add(panel, 1, wx.GROW | wx.ALL, 4)
+        topBox.Add(buttonBox, 0, wx.ALIGN_RIGHT|wx.ALL, 10)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(topBox)
+        topBox.Fit(self)
+        topBox.SetSizeHints(self)
+        self.Layout()
+
+        ###########
+
+        self.Bind(wx.EVT_TEXT, self.OnTitleChanged, id=ID_PROPERTY_TITLE)
+        self.Bind(wx.EVT_BUTTON, self.OnOK, id=wx.ID_OK)
+        self.Bind(wx.EVT_BUTTON, self.OnTry, id=ID_PROPERTY_TRY)
+        self.Bind(wx.EVT_BUTTON, self.OnCloseBtn, id=wx.ID_CANCEL)
+        self.Bind(wx.EVT_BUTTON, self.OnRevert, id=ID_PROPERTY_REVERT)
+
+        ######################
+
+        text_title.SetFocus()
+        self.haveApplied = False
+
+
+    def unsubscribe_messages(self):
+        """Unsubscribe from all messages."""
+        self.parent.Unsubscribe(MAP_REPLACED, self.map_replaced)
+        self.map.Unsubscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)
+
+    def map_layers_removed(self):
+        """Subscribed to MAP_LAYERS_REMOVED. If this layer was removed,
+        Close self.
+        """
+        if self.layer not in self.map.Layers():
+            self.Close()
+
+    def map_replaced(self, *args):
+        """Subscribed to the mainwindow's MAP_REPLACED message. Close self."""
+        self.Close()
+
+    def OnTry(self, event):
+        return
+
+    def OnOK(self, event):
+        self.Close()
+
+    def OnClose(self, event):
+        self.unsubscribe_messages()
+        NonModalNonParentDialog.OnClose(self, event)
+
+    def OnCloseBtn(self, event):
+        """Close is similar to Cancel except that any changes that were
+        made and applied remain applied.
+        """
+
+        self.Close()
+
+    def OnRevert(self, event):
+        return
+
+    def SetTitle(self, title):
+        """Set the title of the dialog."""
+        if title != "":
+            title = ": " + title
+
+        NonModalNonParentDialog.SetTitle(self, _("Layer Properties") + title)
+
+    def OnTitleChanged(self, event):
+        """Update the dialog title when the user changed the layer name."""
+        obj = event.GetEventObject()
+
+        self.layer.SetTitle(obj.GetValue())
+        self.SetTitle(self.layer.Title())
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/legend.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/legend.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/legend.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,788 @@
+# Copyright (c) 2001, 2002, 2003, 2005 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2700 $"
+
+from  math import fabs, cos, pi
+
+from Thuban import _
+
+import resource
+
+import wx
+
+from Thuban.Model.layer import BaseLayer
+from Thuban.Model.map import Map
+from Thuban.Model.classification import ClassGroup
+from Thuban.Model.proj import PROJ_UNITS_DEGREES
+
+from Thuban.Model.messages import \
+    MAP_STACKING_CHANGED, MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED, LAYER_CHANGED,\
+    LAYER_VISIBILITY_CHANGED, TITLE_CHANGED
+
+from Thuban.UI.messages import SCALE_CHANGED
+
+from Thuban.UI.classifier import ClassDataPreviewer
+from Thuban.UI.dock import DockPanel
+from Thuban.UI.scalebar import ScaleBar
+
+from Thuban.UI.menu import Menu
+
+from Thuban.Lib.connector import ConnectorError
+
+ID_LEGEND_TOP = 4001
+ID_LEGEND_RAISE = 4002
+ID_LEGEND_LOWER = 4003
+ID_LEGEND_BOTTOM = 4004
+ID_LEGEND_TREE = 4005
+ID_LEGEND_PROPS = 4006
+ID_LEGEND_SHOWLAYER = 4007
+ID_LEGEND_HIDELAYER = 4008
+
+BMP_SIZE_W = 16
+BMP_SIZE_H = 16
+
+TOP_BMP = "top_layer"
+RAISE_BMP = "raise_layer"
+LOWER_BMP = "lower_layer"
+BOTTOM_BMP = "bottom_layer"
+SHOW_BMP  = "show_layer"
+HIDE_BMP  = "hide_layer"
+PROPS_BMP = "layer_properties"
+
+class LegendPanel(DockPanel):
+
+    def __init__(self, parent, map, mainWindow):
+        DockPanel.__init__(self, parent, -1)
+
+        self.mainWindow = mainWindow
+        self.parent = parent
+
+        self.buttons = []
+
+        panelBox = wx.BoxSizer(wx.VERTICAL)
+
+        self.toolBar = wx.ToolBar(self, -1)
+        self.toolBar.SetToolBitmapSize(wx.Size(24, 24))
+
+        bmp = resource.GetBitmapResource(TOP_BMP, wx.BITMAP_TYPE_XPM)
+        self.toolBar.AddTool(ID_LEGEND_TOP, bmp,
+            shortHelpString=_("Top Layer"))
+
+        bmp = resource.GetBitmapResource(RAISE_BMP, wx.BITMAP_TYPE_XPM)
+        self.toolBar.AddTool(ID_LEGEND_RAISE, bmp,
+            shortHelpString=_("Raise Layer"))
+
+        bmp = resource.GetBitmapResource(LOWER_BMP, wx.BITMAP_TYPE_XPM)
+        self.toolBar.AddTool(ID_LEGEND_LOWER, bmp,
+            shortHelpString=_("Lower Layer"))
+
+        bmp = resource.GetBitmapResource(BOTTOM_BMP, wx.BITMAP_TYPE_XPM)
+        self.toolBar.AddTool(ID_LEGEND_BOTTOM, bmp,
+            shortHelpString=_("Bottom Layer"))
+
+        bmp = resource.GetBitmapResource(SHOW_BMP, wx.BITMAP_TYPE_XPM)
+        self.toolBar.AddTool(ID_LEGEND_SHOWLAYER, bmp,
+            shortHelpString=_("Show Layer"))
+
+        bmp = resource.GetBitmapResource(HIDE_BMP, wx.BITMAP_TYPE_XPM)
+        self.toolBar.AddTool(ID_LEGEND_HIDELAYER, bmp,
+            shortHelpString=_("Hide Layer"))
+
+        bmp = resource.GetBitmapResource(PROPS_BMP, wx.BITMAP_TYPE_XPM)
+        self.toolBar.AddTool(ID_LEGEND_PROPS, bmp,
+            shortHelpString=_("Edit Layer Properties"))
+
+        self.toolBar.Realize()
+        panelBox.Add(self.toolBar, 0, wx.GROW, 0)
+
+        self.Bind(wx.EVT_TOOL, self._OnMoveTop, id=ID_LEGEND_TOP)
+        self.Bind(wx.EVT_TOOL, self._OnMoveUp, id=ID_LEGEND_RAISE)
+        self.Bind(wx.EVT_TOOL, self._OnMoveDown, id=ID_LEGEND_LOWER)
+        self.Bind(wx.EVT_TOOL, self._OnMoveBottom, id=ID_LEGEND_BOTTOM)
+        self.Bind(wx.EVT_TOOL, self._OnProperties, id=ID_LEGEND_PROPS)
+        self.Bind(wx.EVT_TOOL, self._OnShowLayer, id=ID_LEGEND_SHOWLAYER)
+        self.Bind(wx.EVT_TOOL, self._OnHideLayer, id=ID_LEGEND_HIDELAYER)
+
+        self.tree = LegendTree(self, ID_LEGEND_TREE, map, mainWindow)
+
+        panelBox.Add(self.tree, 1, wx.GROW, 0)
+
+        self.scalebarbitmap = ScaleBarBitmap(self, map, mainWindow)
+        panelBox.Add(self.scalebarbitmap, 0, wx.GROW, 0)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(panelBox)
+        panelBox.SetSizeHints(self)
+
+
+        self.panelBox = panelBox
+
+        self.__EnableButtons(False)
+
+        self.Create()
+
+        self.Bind(wx.EVT_CLOSE, self._OnClose)
+
+
+    def GetMap(self):
+        return self.tree.GetMap()
+
+    def SetMap(self, map):
+        self.tree.SetMap(map)
+        self.scalebarbitmap.SetCanvas(self.mainWindow.canvas)
+
+    def DoOnSelChanged(self, layer, group):
+
+        ok = isinstance(layer, BaseLayer)
+        self.__EnableButtons(ok)
+
+        self.mainWindow.SelectLayer(layer)
+
+    def DoOnProperties(self):
+        list = self.tree.GetSelectedHierarchy()
+
+        ok = isinstance(list[0], BaseLayer)
+        if ok:
+            self.mainWindow.OpenLayerProperties(list[0], list[1])
+
+    def Destroy(self):
+        self.__Close()
+
+    def _OnProperties(self, event):
+        self.DoOnProperties()
+
+    def _OnMoveTop(self, event):
+        self.tree.MoveCurrentItemTop()
+
+    def _OnMoveUp(self, event):
+        self.tree.MoveCurrentItemUp()
+
+    def _OnMoveDown(self, event):
+        self.tree.MoveCurrentItemDown()
+
+    def _OnMoveBottom(self, event):
+        self.tree.MoveCurrentItemBottom()
+
+    def _OnShowLayer(self, event):
+        self.tree.DoOnShowLayer()
+        pass
+
+    #def Close(self, force = False):
+        #DockPanel.Close(self, force)
+
+    def _OnClose(self, event):
+        self.__Close()
+
+    def _OnHideLayer(self, event):
+        self.tree.DoOnHideLayer()
+        pass
+
+    def _OnToggleVisibility(self, event):
+        self.tree.ToggleVisibility()
+
+    def _OnProjection(self, event):
+        self.tree.LayerProjection()
+
+    def _OnRemoveLayer(self, event):
+        self.mainWindow.RemoveLayer()
+
+    def _OnShowTable(self, event):
+        self.mainWindow.LayerShowTable()
+
+    def __EnableButtons(self, on):
+        self.toolBar.EnableTool(ID_LEGEND_TOP, on)
+        self.toolBar.EnableTool(ID_LEGEND_RAISE, on)
+        self.toolBar.EnableTool(ID_LEGEND_LOWER, on)
+        self.toolBar.EnableTool(ID_LEGEND_BOTTOM, on)
+        self.toolBar.EnableTool(ID_LEGEND_SHOWLAYER,  on)
+        self.toolBar.EnableTool(ID_LEGEND_HIDELAYER,  on)
+        self.toolBar.EnableTool(ID_LEGEND_PROPS, on)
+
+    def __Close(self):
+        self.tree.Close()
+
+class LegendTree(wx.TreeCtrl):
+
+    def __init__(self, parent, id, map, mainWindow):
+        wx.TreeCtrl.__init__(self, parent, id,
+                            style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT,
+                            size = (200, 200))
+
+        self.mainWindow = mainWindow
+        self.map = None
+        self.parent = parent
+        self.changing_selection = 0
+
+        #
+        # The image list used by the wxTreeCtrl causes problems when
+        # we remove layers and/or change a classification because it
+        # changes the image indices if you remove images from the list.
+        # Rather than removing unused images we use this list to keep 
+        # track of which indices are available in the image list 
+        # (because of a previous removal) and then  replace those indices 
+        # with new images rather than appending to the end of the image 
+        # list (assuming there are any that are available).
+        #
+        self.availImgListIndices = []
+
+        self.image_list = None
+        self.emptyImageIndex = 0
+
+        self.previewer = ClassDataPreviewer()
+
+        self.preventExpandCollapse = False
+        self.raiseProperties = False
+
+        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._OnItemActivated, id=ID_LEGEND_TREE)
+        self.Bind(wx.EVT_TREE_SEL_CHANGED, self._OnSelChanged, id=ID_LEGEND_TREE)
+        self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpandCollapse, id=ID_LEGEND_TREE)
+        self.Bind(wx.EVT_TREE_ITEM_COLLAPSING, self.OnItemExpandCollapse, id=ID_LEGEND_TREE)
+        self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self._OnRightClick, id=ID_LEGEND_TREE)
+
+        self.Bind(wx.EVT_CLOSE, self._OnClose)
+
+        self.SetMap(map)
+
+    def _OnRightClick(self, event):
+        """Select item and pop up a context menu"""
+
+        # The pop up menu is related to the legend tree, so we have direct 
+        # access on the tree items. The events issued by the menu are handled
+        # by the legend panel, since most of the handlers are already
+        # implemented there.
+
+        # Update item selection to the right click
+        item = event.GetItem()
+        self.SelectItem(item)
+
+        # Define the menu
+        popup_menu = Menu("PopUp", "",
+                          [ "layer_visibility",
+                            None,
+                            "layer_properties",
+                            "layer_projection",
+                            "layer_remove",
+                            "layer_show_table",
+                            None,
+                            "layer_to_top",
+                            "layer_raise",
+                            "layer_lower",
+                            "layer_to_bottom"
+                            ])
+
+        # Display the menu
+        pos = event.GetPoint()
+        shift = self.ClientToScreen((0,0))
+        self.PopupMenu(self.mainWindow.build_menu(popup_menu), pos)
+
+    def find_layer(self, layer):
+        """Return the tree item for the layer"""
+        root = self.GetRootItem()
+        id, cookie = self.GetFirstChild(root)
+        while id.IsOk():
+            if self.GetPyData(id) is layer:
+                return id
+            id, cookie = self.GetNextChild(root, cookie)
+        return None
+
+    def _OnClose(self, event):
+        self.SetMap(None)
+
+    def GetMap(self):
+        return self.map
+
+    def SetMap(self, map):
+
+        sub_list = [(MAP_STACKING_CHANGED, self._OnMsgMapStackingChanged),
+                    (MAP_LAYERS_ADDED, self._OnMsgMapLayersAdded),
+                    (MAP_LAYERS_REMOVED, self._OnMsgMapLayersRemoved)]
+
+        if self.map is not None:
+            for msg, func in sub_list: self.map.Unsubscribe(msg, func)
+            #self.mainWindow.application.Unsubscribe(SESSION_REPLACED, 
+                #self._OnMsgMapsChanged)
+            #try:
+                #self.mainWindow.application.session.Unsubscribe(MAPS_CHANGED, 
+                    #self._OnMsgMapsChanged)
+            #except ConnectorError:
+                #pass
+            self.DeleteAllItems()
+
+        self.map = map
+
+        if self.map is not None:
+            for msg, func in sub_list: self.map.Subscribe(msg, func)
+            #self.mainWindow.application.session.Subscribe(MAPS_CHANGED, 
+                #self._OnMsgMapsChanged)
+            #self.mainWindow.application.Subscribe(SESSION_REPLACED, 
+                #self._OnMsgMapsChanged)
+            self.__FillTree(self.map)
+
+    def MoveCurrentItemTop(self):
+        layer, group = self.GetSelectedHierarchy()
+
+        if layer is not None:
+            self.map.MoveLayerToTop(layer)
+        else:
+            assert False, "Shouldn't be allowed."
+            pass
+
+    def MoveCurrentItemUp(self):
+        layer, group = self.GetSelectedHierarchy()
+
+        if layer is not None:
+            self.map.RaiseLayer(layer)
+        else:
+            assert False, "Shouldn't be allowed."
+            pass
+
+    def MoveCurrentItemDown(self):
+        layer, group = self.GetSelectedHierarchy()
+
+        if layer is not None:
+            self.map.LowerLayer(layer)
+        else:
+            assert False, "Shouldn't be allowed."
+            pass
+
+    def MoveCurrentItemBottom(self):
+        layer, group = self.GetSelectedHierarchy()
+
+        if layer is not None:
+            self.map.MoveLayerToBottom(layer)
+        else:
+            assert False, "Shouldn't be allowed."
+            pass
+
+    def OnCompareItems(self, item1, item2):
+
+        data1 = self.GetPyData(item1)
+        data2 = self.GetPyData(item2)
+
+        if isinstance(data1, BaseLayer):
+            layers = self.map.Layers()
+            return layers.index(data2) - layers.index(data1)
+        else:
+            return wx.TreeCtrl.OnCompareItems(self, item1, item2)
+
+    def DoOnShowLayer(self):
+        layer, group = self.GetSelectedHierarchy()
+        layer.SetVisible(True)
+
+    def DoOnHideLayer(self):
+        layer, group = self.GetSelectedHierarchy()
+        layer.SetVisible(False)
+
+    def ToggleVisibility(self):
+        layer, group = self.GetSelectedHierarchy()
+
+        layer.SetVisible(not layer.Visible())
+
+    def LayerProjection(self):
+        self.parent.mainWindow.LayerProjection()
+
+    def Sort(self):
+        self.SortChildren(self.GetRootItem())
+
+    def GetSelectedHierarchy(self):
+        id = self.GetSelection()
+
+        if not id.IsOk():
+            return (None, None)
+
+        layer = self.GetPyData(id)
+        group = None
+
+        if isinstance(layer, ClassGroup):
+            id = self.GetItemParent(id)
+            assert id.IsOk()
+            group = layer
+            layer = self.GetPyData(id)
+
+        return (layer, group)
+
+    def _OnMsgMapsChanged(self):
+        #print self.map is self.mainWindow.Map()
+        self.SetMap(self.mainWindow.Map())
+
+    def _OnSelChanged(self, event):
+        # If we change the selection from normalize_selection do nothing.
+        if self.changing_selection:
+            return
+
+        self.normalize_selection()
+        self.__UpdateSelection()
+
+    def normalize_selection(self):
+        """Select the layer containing currently selected item"""
+        # This is really a workaround for a bug in wx where deleting a
+        # subtree with DeleteChildren does not update the selection
+        # properly and can lead to segfaults later because the return
+        # value of GetSelection points to invalid data.
+        item = self.GetSelection()
+        while item.IsOk():
+            object = self.GetPyData(item)
+            if isinstance(object, BaseLayer):
+                break
+            item = self.GetItemParent(item)
+        else:
+            # No layer was found in the chain of parents, so there's
+            # nothing we can do.
+            return
+
+        self.changing_selection = 1
+        try:
+            self.SelectItem(item)
+        finally:
+            self.changing_selection = 0
+
+
+    def OnItemExpandCollapse(self, event):
+        if self.preventExpandCollapse:
+            event.Veto()
+            self.preventExpandCollapse = False
+
+    def _OnItemActivated(self, event):
+        # The following looks strange but is need under Windows to
+        # raise the Properties on double-click: The tree control
+        # always gets an Expanded / Collapsed event after the ItemActivated
+        # on double click, which raises the main window again. We add a second
+        # ItemActivated event to the queue, which simply raises the already
+        # displayed window.
+        if self.raiseProperties:
+            self.parent.DoOnProperties()
+            self.raiseProperties = False
+        else:
+            self.raiseProperties = True
+            self.preventExpandCollapse = True
+            self.parent.DoOnProperties()
+            self.AddPendingEvent(event)
+
+    def _OnMsgLayerChanged(self, layer):
+        assert isinstance(layer, BaseLayer)
+
+        id = self.find_layer(layer)
+        assert id is not None
+
+        self.__FillTreeLayer(id)
+        self.__UpdateSelection()
+
+    def _OnMsgMapStackingChanged(self, *args):
+        self.Sort()
+        id = self.GetSelection()
+
+        if id.IsOk():
+            self.EnsureVisible(id)
+        self.__UpdateSelection()
+
+    def _OnMsgMapLayersAdded(self, map):
+        assert map is self.map
+
+        # Build a dict with all layers known by the the tree as keys
+        layers = {}
+        root = self.GetRootItem()
+        id, cookie = self.GetFirstChild(root)
+        while id.IsOk():
+            layers[self.GetPyData(id)] = 1
+            id, cookie = self.GetNextChild(root, cookie)
+
+        # Add layers in the map but not in the dict
+        i = 0
+        for l in map.Layers():
+            if not l in layers:
+                self.__AddLayer(i, l)
+
+        self.__UpdateSelection()
+
+    def _OnMsgMapLayersRemoved(self, map):
+        assert map is self.map
+
+        layers = map.Layers()
+
+        root = self.GetRootItem()
+        id, cookie = self.GetFirstChild(root)
+        while id.IsOk():
+            if self.GetPyData(id) not in layers:
+                self.__RemoveLayer(id)
+            id, cookie = self.GetNextChild(root, cookie)
+
+
+        self.__UpdateSelection()
+
+    def _OnMsgLayerVisibilityChanged(self, layer):
+        assert isinstance(layer, BaseLayer)
+
+        self.__ShowHideLayer(layer)
+        self.__UpdateSelection()
+
+    def _OnMsgLayerTitleChanged(self, layer):
+
+        id = self.find_layer(layer)
+        if id.IsOk():
+            self.SetItemText(id, layer.Title())
+        self.__UpdateSelection()
+
+    def __UpdateSelection(self):
+        layer, group = self.GetSelectedHierarchy()
+        self.parent.DoOnSelChanged(layer, group)
+
+    def __FillTree(self, map):
+
+        self.Freeze()
+
+        self.DeleteAllItems()
+
+        if map.HasLayers():
+            root = self.GetRootItem()
+            for l in map.Layers():
+                self.__AddLayer(0, l)
+
+        self.Thaw()
+
+    def __FillTreeLayer(self, pid):
+
+        layer = self.GetPyData(pid)
+
+        self.Freeze()
+
+        self.DeleteChildren(pid)
+
+        if layer.HasClassification():
+
+            clazz = layer.GetClassification()
+
+            shapeType = layer.ShapeType()
+
+            show = layer.Visible()
+            for g in clazz:
+                if g.IsVisible():
+                    id = self.AppendItem(pid, g.GetDisplayText())
+                    self.SetPyData(id, g)
+                    self.__SetVisibilityStyle(show, id)
+
+                    bmp = self.__BuildGroupImage(g, shapeType)
+
+                    if bmp is None:
+                        self.SetItemImage(id, -1, wx.TreeItemIcon_Normal)
+                        self.SetItemImage(id, -1, wx.TreeItemIcon_Selected)
+                        #self.SetItemSelectedImage(id, -1)
+                    else:
+                        if self.availImgListIndices:
+                            i = self.availImgListIndices.pop(0)
+                            self.image_list.Replace(i, bmp)
+                        else:
+                            i = self.image_list.Add(bmp)
+
+                        self.SetItemImage(id, i, wx.TreeItemIcon_Normal)
+                        self.SetItemImage(id, i, wx.TreeItemIcon_Selected)
+                        #self.SetItemlectedImage(id, i)
+
+        self.Thaw()
+
+    def __BuildGroupImage(self, group, shapeType):
+
+        bmp = wx.EmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)
+        #brush = wxBrush(Color2wxColour(item[1]), wxSOLID)
+        dc = wx.MemoryDC()
+        dc.SelectObject(bmp)
+        dc.Clear()
+
+        self.previewer.Draw(dc, None, group.GetProperties(), shapeType)
+
+        return bmp
+
+    def DeleteAllItems(self):
+
+        pid = self.GetRootItem()
+
+        id, cookie = self.GetFirstChild(pid)
+        while id.IsOk():
+            self.__RemoveLayer(id)
+            id, cookie = self.GetNextChild(pid, cookie)
+
+        wx.TreeCtrl.DeleteAllItems(self)
+
+    def __AddLayer(self, before, l):
+        root = self.GetRootItem()
+        id = self.InsertItemBefore(root, before,
+                            l.Title(),
+                            self.mapImageIndex,
+                            self.mapImageIndex)
+
+        self.SetPyData(id, l)
+        self.__SetVisibilityStyle(l.Visible(), id)
+
+        self.__FillTreeLayer(id)
+        self.Expand(id)
+
+        l.Subscribe(LAYER_CHANGED, self._OnMsgLayerChanged)
+        l.Subscribe(LAYER_VISIBILITY_CHANGED,
+                    self._OnMsgLayerVisibilityChanged)
+        l.Subscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)
+
+    def __RemoveLayer(self, id):
+        self.DeleteChildren(id)
+
+        layer = self.GetPyData(id)
+        layer.Unsubscribe(LAYER_CHANGED,
+                          self._OnMsgLayerChanged)
+        layer.Unsubscribe(LAYER_VISIBILITY_CHANGED,
+                          self._OnMsgLayerVisibilityChanged)
+        layer.Unsubscribe(TITLE_CHANGED, self._OnMsgLayerTitleChanged)
+
+        self.Delete(id)
+
+    def DeleteChildren(self, pid):
+        id, cookie = self.GetFirstChild(pid)
+        while id.IsOk():
+            self.availImgListIndices.append(self.GetItemImage(id))
+            id, cookie = self.GetNextChild(pid, cookie)
+        wx.TreeCtrl.DeleteChildren(self, pid)
+
+    def GetRootItem(self):
+        root = wx.TreeCtrl.GetRootItem(self)
+
+        if not root.IsOk():
+            self.image_list = wx.ImageList(BMP_SIZE_W, BMP_SIZE_H, False, 0)
+
+            bmp = wx.EmptyBitmap(BMP_SIZE_W, BMP_SIZE_H)
+            dc = wx.MemoryDC()
+            dc.SelectObject(bmp)
+            dc.SetBrush(wx.BLACK_BRUSH)
+            dc.Clear()
+            dc.SelectObject(wx.NullBitmap)
+
+            self.emptyImageIndex = \
+                self.image_list.AddWithColourMask(bmp, wx.Colour(0, 0, 0))
+
+            bmp = resource.GetBitmapResource("legend_icon_layer",
+                                              wx.BITMAP_TYPE_XPM)
+            self.mapImageIndex = \
+                self.image_list.Add(bmp)
+
+            self.AssignImageList(self.image_list)
+            self.availImgListIndices = []
+
+            root = self.AddRoot("")
+
+        return root
+
+    def __SetVisibilityStyle(self, visible, id):
+        font = self.GetItemFont(id)
+
+        if visible:
+            font.SetStyle(wx.NORMAL)
+            color = wx.BLACK
+        else:
+            #font.SetStyle(wxITALIC)
+            font.SetStyle(wx.NORMAL)
+            color = wx.LIGHT_GREY
+
+        self.SetItemTextColour(id, color)
+        self.SetItemFont(id, font)
+
+    def __ShowHideLayer(self, layer):
+        parent = self.find_layer(layer)
+        assert parent.IsOk()
+
+        visible = layer.Visible()
+
+        self.__SetVisibilityStyle(visible, parent)
+
+        id, cookie = self.GetFirstChild(parent)
+
+        while id.IsOk():
+            self.__SetVisibilityStyle(visible, id)
+            id, cookie = self.GetNextChild(parent, cookie)
+
+    # In wxPython 2.4 the GetFirstChild method has to be called with a
+    # second argument and in 2.5 it must not.  Reading the code of
+    # wxPython 2.4 it seems that the second parameter was intended to be
+    # optional there but due to a bug in the C++ code it doesn't work
+    # and omitting the second argument leads to a segfault.  To cope
+    # with this and to make the code usable with both 2.5 and 2.4 we
+    # overwrite the inherited method when running with 2.4 to provide a
+    # default value for the second argument.
+    if map(int, wx.__version__.split(".")[:2]) < [2, 5]:
+        def GetFirstChild(self, item):
+            return wx.TreeCtrl.GetFirstChild(self, item, 0)
+
+
+class ScaleBarBitmap(wx.BoxSizer):
+
+    def __init__(self, parent, map, mainWindow):
+        # While the width is fixed, get the height _now_.
+        dc = wx.MemoryDC()
+        textwidth, textheight = dc.GetTextExtent("%d"%0)
+        self.width = 210
+        self.height = textheight + 3*2 + 8
+
+        wx.BoxSizer.__init__(self, wx.VERTICAL)
+        bmp=wx.EmptyBitmap(self.width, self.height)
+        self.scalebarBitmap = wx.StaticBitmap(parent, -1, bmp)
+        self.Add(self.scalebarBitmap, 0, wx.ALIGN_CENTER|wx.LEFT|wx.TOP|wx.RIGHT, 1)
+
+        self.mainWindow = mainWindow
+        self.parent = parent
+        self.canvas = None
+        self.SetCanvas(self.mainWindow.canvas)
+
+    def SetCanvas(self, canvas):
+        sub_list = [(SCALE_CHANGED, self._OnMsgScaleChanged)]
+
+        if self.canvas is not None:
+            for msg, func in sub_list: self.canvas.Unsubscribe(msg, func)
+
+        self.canvas = canvas
+        self.scalebar = ScaleBar(canvas.map)
+
+        if self.canvas is not None:
+            for msg, func in sub_list: self.canvas.Subscribe(msg, func)
+            self.__SetScale(self.canvas.scale)
+
+    def _OnMsgScaleChanged(self, scale):
+        self.__SetScale(scale)
+
+    def __SetScale(self, scale):
+        bmp = wx.EmptyBitmap(self.width, self.height)
+        dc = wx.MemoryDC()
+        dc.SelectObject(bmp)
+        dc.Clear()
+
+        if self.canvas.map is not None \
+            and self.canvas.map.projection is not None:
+
+            # if we are using a projection with geographics coordinates
+            # we need to change the scale value based on where we are
+            # on the globe.
+            if self.canvas.map.projection.GetProjectedUnits() \
+                == PROJ_UNITS_DEGREES:
+
+                width, height = self.canvas.GetSizeTuple()
+                long, lat = self.canvas.win_to_proj(width/2, height/2)
+
+                # slightly inaccurate, but if we are looking at
+                # the north/south pole we could end up dividing by zero
+                #
+                # it shouldn't matter for our purposes that we ignore
+                # the original sign of lat.
+                if fabs(lat) > 89.9: lat = 89.9
+
+                #
+                # one degree is about 111,133m at the equator
+                # we need to adjust that for latitude as 
+                # we move north/south. use the center of the map
+                # as the point to scale the length to.
+                #
+                scale = scale / (111133.0 * fabs(cos(lat * pi/180)))
+
+            self.scalebar.DrawScaleBar(scale, dc, (0,0), dc.GetSizeTuple())
+
+        self.scalebarBitmap.SetBitmap(bmp)
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/main.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/main.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/main.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,75 @@
+# Copyright (C) 2001, 2002, 2003 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+The main entry point for the Thuban GUI.
+"""
+
+__version__ = "$Revision: 2700 $"
+
+import sys
+import getopt
+
+import application
+import Thuban.version
+
+
+class options:
+
+    attribute_editing_enabled = False
+
+
+def main():
+    """Instantiate the application object and run the application"""
+
+    if verify_versions():
+        app = application.ThubanApplication(0)
+        opts, args = getopt.getopt(sys.argv[1:], '',
+                                   ['enable-attribute-editing'])
+        for optchar, value in opts:
+            if optchar == '--enable-attribute-editing':
+                options.attribute_editing_enabled = True
+            else:
+                print >>sys.stderr, "Unknown option", optchar
+
+        # If there was a non-flag argument it's the name of a thuban
+        # file.
+        if args:
+            app.OpenSession(args[0])
+
+        app.MainLoop()
+        # sys.excepthook is set in ThubanApplication.OnInit()
+        sys.excepthook = sys.__excepthook__
+
+
+def verify_versions():
+    """Check some library versions.
+
+    Print a message containing any libraries which are wrong.
+    Return True if everything is OK, otherwise False.
+    """
+
+    errors = Thuban.version.verify_versions()
+
+    if len(errors) > 0:
+        msg = " The following version errors were detected:"
+
+        for e in errors:
+            msg += "\n     " + e
+
+#       if use_msg_box:
+#           # XXX: use a message box to display the errors
+#           pass
+
+        print "\n*******************************************************"
+        print msg
+        print "*******************************************************\n"
+
+        return False
+
+    return True

Added: packages/thuban/branches/upstream/current/Thuban/UI/mainwindow.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/mainwindow.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/mainwindow.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1370 @@
+# Copyright (C) 2001, 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+# Bernhard Herzog <bh at intevation.de>
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+The main window
+"""
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: mainwindow.py 2700 2006-09-18 14:27:02Z dpinte $
+
+import os
+import copy
+
+import wx
+
+import Thuban
+
+from Thuban import _
+from Thuban.Model.messages import TITLE_CHANGED, LAYER_PROJECTION_CHANGED, \
+     MAP_PROJECTION_CHANGED, MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED
+
+from Thuban.Model.session import create_empty_session
+from Thuban.Model.layer import Layer, RasterLayer
+from Thuban.Model.postgisdb import PostGISShapeStore, has_postgis_support
+from wx.lib.dialogs import MultipleChoiceDialog
+
+import view
+import tree
+import tableview, identifyview
+import legend
+from menu import Menu
+
+from context import Context
+from command import registry, Command, ToolCommand
+from messages import LAYER_SELECTED, SHAPES_SELECTED, VIEW_POSITION, \
+     MAP_REPLACED
+from about import About
+
+from Thuban.UI.dock import DockFrame
+from Thuban.UI.join import JoinDialog
+from Thuban.UI.dbdialog import DBFrame, DBDialog, ChooseDBTableDialog
+import resource
+import Thuban.Model.resource
+
+import projdialog
+
+from Thuban.UI.classifier import Classifier
+from Thuban.UI.rasterlayerproperties import RasterLayerProperties
+from Thuban.Model.layer import RasterLayer
+
+from Thuban.Lib.classmapper import ClassMapper
+
+layer_properties_dialogs = ClassMapper()
+layer_properties_dialogs.add(RasterLayer, RasterLayerProperties)
+layer_properties_dialogs.add(Layer, Classifier)
+
+class MainWindow(DockFrame):
+
+    # Some messages that can be subscribed/unsubscribed directly through
+    # the MapCanvas come in fact from other objects. This is a map to
+    # map those messages to the names of the instance variables they
+    # actually come from. This delegation is implemented in the
+    # Subscribe and unsubscribed methods
+    delegated_messages = {LAYER_SELECTED: "canvas",
+                          SHAPES_SELECTED: "canvas",
+                          MAP_REPLACED: "canvas"}
+
+    # Methods delegated to some instance variables. The delegation is
+    # implemented in the __getattr__ method.
+    delegated_methods = {"SelectLayer": "canvas",
+                         "SelectShapes": "canvas",
+                         "SelectedLayer": "canvas",
+                         "SelectedShapes": "canvas",
+                         }
+
+    # Messages from the canvas that may require a status bar update.
+    # The update_status_bar method will be subscribed to these messages.
+    update_status_bar_messages = (VIEW_POSITION, LAYER_PROJECTION_CHANGED,
+                                  MAP_PROJECTION_CHANGED, MAP_LAYERS_ADDED,
+                                  MAP_LAYERS_REMOVED)
+
+    def __init__(self, parent, ID, title, application, interactor,
+                 initial_message = None, size = wx.Size(-1, -1)):
+        DockFrame.__init__(self, parent, ID, title, wx.DefaultPosition, size)
+        #wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, size)
+
+        self.application = application
+
+        self.CreateStatusBar()
+        if initial_message:
+            self.SetStatusText(initial_message)
+
+        self.identify_view = None
+
+        self.init_ids()
+
+        # creat the menubar from the main_menu description
+        self.SetMenuBar(self.build_menu_bar(main_menu))
+
+        # Similarly, create the toolbar from main_toolbar
+        toolbar = self.build_toolbar(main_toolbar)
+        # call Realize to make sure that the tools appear.
+        toolbar.Realize()
+
+
+        # Create the map canvas
+        canvas = view.MapCanvas(self, -1)
+        canvas.Subscribe(SHAPES_SELECTED, self.identify_view_on_demand)
+        self.canvas = canvas
+        self.canvas.Subscribe(TITLE_CHANGED, self.title_changed)
+
+        for channel in self.update_status_bar_messages:
+            self.canvas.Subscribe(channel, self.update_status_bar)
+
+        self.SetMainWindow(self.canvas)
+
+        self.SetAutoLayout(True)
+
+        self.init_dialogs()
+
+        self.ShowLegend()
+
+        self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+    def Subscribe(self, channel, *args):
+        """Subscribe a function to a message channel.
+
+        If channel is one of the delegated messages call the appropriate
+        object's Subscribe method. Otherwise do nothing.
+        """
+        if channel in self.delegated_messages:
+            object = getattr(self, self.delegated_messages[channel])
+            object.Subscribe(channel, *args)
+        else:
+            print "Trying to subscribe to unsupported channel %s" % channel
+
+    def Unsubscribe(self, channel, *args):
+        """Unsubscribe a function from a message channel.
+
+        If channel is one of the delegated messages call the appropriate
+        object's Unsubscribe method. Otherwise do nothing.
+        """
+        if channel in self.delegated_messages:
+            object = getattr(self, self.delegated_messages[channel])
+            try:
+                object.Unsubscribe(channel, *args)
+            except wx.PyDeadObjectError:
+                # The object was a wxObject and has already been
+                # destroyed. Hopefully it has unsubscribed all its
+                # subscribers already so that it's OK if we do nothing
+                # here
+                pass
+
+    def __getattr__(self, attr):
+        """If attr is one of the delegated methods return that method
+
+        Otherwise raise AttributeError.
+        """
+        if attr in self.delegated_methods:
+            return getattr(getattr(self, self.delegated_methods[attr]), attr)
+        raise AttributeError(attr)
+
+    def init_ids(self):
+        """Initialize the ids"""
+        self.current_id = 6000
+        self.id_to_name = {}
+        self.name_to_id = {}
+        self.events_bound = {}
+
+    def get_id(self, name):
+        """Return the wxWindows id for the command named name.
+
+        Create a new one if there isn't one yet"""
+        ID = self.name_to_id.get(name)
+        if ID is None:
+            ID = self.current_id
+            self.current_id = self.current_id + 1
+            self.name_to_id[name] = ID
+            self.id_to_name[ID] = name
+        return ID
+
+    def bind_command_events(self, command, ID):
+        """Bind the necessary events for the given command and ID"""
+        if not self.events_bound.has_key(ID):
+            # the events haven't been bound yet
+            self.Bind(wx.EVT_MENU, self.invoke_command, id=ID)
+            if command.IsDynamic():
+                self.Bind(wx.EVT_UPDATE_UI, self.update_command_ui, id=ID)
+
+    def build_menu_bar(self, menudesc):
+        """Build and return the menu bar from the menu description"""
+        menu_bar = wx.MenuBar()
+
+        for item in menudesc.items:
+            # here the items must all be Menu instances themselves
+            menu_bar.Append(self.build_menu(item), item.title)
+
+        return menu_bar
+
+    def build_menu(self, menudesc):
+        """Return a wxMenu built from the menu description menudesc"""
+        wxmenu = wx.Menu()
+        last = None
+        for item in menudesc.items:
+            if item is None:
+                # a separator. Only add one if the last item was not a
+                # separator
+                if last is not None:
+                    wxmenu.AppendSeparator()
+            elif isinstance(item, Menu):
+                # a submenu
+                wxmenu.AppendMenu(wx.NewId(), item.title, self.build_menu(item))
+            else:
+                # must the name the name of a command
+                self.add_menu_command(wxmenu, item)
+            last = item
+        return wxmenu
+
+    def build_toolbar(self, toolbardesc):
+        """Build and return the main toolbar window from a toolbar description
+
+        The parameter should be an instance of the Menu class but it
+        should not contain submenus.
+        """
+        toolbar = self.CreateToolBar(wx.TB_3DBUTTONS)
+
+        # set the size of the tools' bitmaps. Not needed on wxGTK, but
+        # on Windows, although it doesn't work very well there. It seems
+        # that only 16x16 icons are really supported on windows.
+        # We probably shouldn't hardwire the bitmap size here.
+        toolbar.SetToolBitmapSize(wx.Size(24, 24))
+
+        for item in toolbardesc.items:
+            if item is None:
+                toolbar.AddSeparator()
+            else:
+                # assume it's a string.
+                self.add_toolbar_command(toolbar, item)
+
+        return toolbar
+
+    def add_menu_command(self, menu, name):
+        """Add the command with name name to the menu menu.
+
+        If name is None, add a separator.
+        """
+        if name is None:
+            menu.AppendSeparator()
+        else:
+            command = registry.Command(name)
+            if command is not None:
+                ID = self.get_id(name)
+                menu.Append(ID, command.Title(), command.HelpText(),
+                            command.IsCheckCommand())
+                self.bind_command_events(command, ID)
+            else:
+                print _("Unknown command %s") % name
+
+    def add_toolbar_command(self, toolbar, name):
+        """Add the command with name name to the toolbar toolbar.
+
+        If name is None, add a separator.
+        """
+        # Assume that all toolbar commands are also menu commmands so
+        # that we don't have to add the event handlers here
+        if name is None:
+            toolbar.AddSeparator()
+        else:
+            command = registry.Command(name)
+            if command is not None:
+                ID = self.get_id(name)
+                bitmap = resource.GetBitmapResource(command.Icon(),
+                                                    wx.BITMAP_TYPE_XPM)
+                toolbar.AddTool(ID, bitmap,
+                                shortHelpString = command.HelpText(),
+                                isToggle = command.IsCheckCommand())
+                self.bind_command_events(command, ID)
+            else:
+                print _("Unknown command %s") % name
+
+    def Context(self):
+        """Return the context object for a command invoked from this window
+        """
+        return Context(self.application, self.application.Session(), self)
+
+    def invoke_command(self, event):
+        name = self.id_to_name.get(event.GetId())
+        if name is not None:
+            command = registry.Command(name)
+            command.Execute(self.Context())
+        else:
+            print _("Unknown command ID %d") % event.GetId()
+
+    def update_command_ui(self, event):
+        #print "update_command_ui", self.id_to_name[event.GetId()]
+        context = self.Context()
+        command = registry.Command(self.id_to_name[event.GetId()])
+        if command is not None:
+            sensitive = command.Sensitive(context)
+            event.Enable(sensitive)
+            if command.IsTool() and not sensitive and command.Checked(context):
+                # When a checked tool command is disabled deselect all
+                # tools. Otherwise the tool would remain active but it
+                # might lead to errors if the tools stays active. This
+                # problem occurred in GREAT-ER and this fixes it, but
+                # it's not clear to me whether this is really the best
+                # way to do it (BH, 20021206).
+                self.canvas.SelectTool(None)
+            event.SetText(command.DynText(context))
+            if command.IsCheckCommand():
+                    event.Check(command.Checked(context))
+
+    def RunMessageBox(self, title, text, flags = wx.OK | wx.ICON_INFORMATION):
+        """Run a modal message box with the given text, title and flags
+        and return the result"""
+        dlg = wx.MessageDialog(self, text, title, flags)
+        dlg.CenterOnParent()
+        result = dlg.ShowModal()
+        dlg.Destroy()
+        return result
+
+    def init_dialogs(self):
+        """Initialize the dialog handling"""
+        # The mainwindow maintains a dict mapping names to open
+        # non-modal dialogs. The dialogs are put into this dict when
+        # they're created and removed when they're closed
+        self.dialogs = {}
+
+    def add_dialog(self, name, dialog):
+        if self.dialogs.has_key(name):
+            raise RuntimeError(_("The Dialog named %s is already open") % name)
+        self.dialogs[name] = dialog
+
+    def dialog_open(self, name):
+        return self.dialogs.has_key(name)
+
+    def remove_dialog(self, name):
+        del self.dialogs[name]
+
+    def get_open_dialog(self, name):
+        return self.dialogs.get(name)
+
+    def update_status_bar(self, *args):
+        """Handler for a bunch of messages that may require a status bar update
+
+        Currently this handles the canvas' VIEW_POSITION_CHANGED
+        messages as well as several messages about changes in the map
+        which may affect whether and how projections are used.
+
+        These messages affect the text in the status bar in the following way:
+
+        When VIEW_POSITION_CHANGED messages are sent and the mouse is
+        actually in the canvas window, display the current mouse
+        coordinates as defined by the canvas' CurrentPosition method.
+
+        If there is no current position to show, check whether there is
+        a potential problem with the map and layer projections and
+        display a message about it.  Otherwise the status bar will
+        become empty.
+
+        The text is displayed in the status bar using the
+        set_position_text method.
+        """
+        # Implementation note: We do not really have to know which
+        # message was sent.  We can simply call the canvas'
+        # CurrentPosition method and if that returns a tuple, it was a
+        # VIEW_POSITION_CHANGED message and we have to display it.
+        # Otherwise it was a VIEW_POSITION_CHANGED message where the
+        # mouse has left the canvas or it was a message about a change
+        # to the map, in which case we check the projections.
+        #
+        # When changing this method, keep in mind that the
+        # VIEW_POSITION_CHANGED message are sent for every mouse move in
+        # the canvas window, that is they happen very often, so the path
+        # taken in that case has to be fast.
+        text = ""
+        pos = self.canvas.CurrentPosition()
+        if pos is not None:
+            text = "(%10.10g, %10.10g)" % pos
+        else:
+            for layer in self.canvas.Map().Layers():
+                bbox = layer.LatLongBoundingBox()
+                if bbox:
+                    left, bottom, right, top = bbox
+                    if not (-180 <= left <= 180 and
+                            -180 <= right <= 180 and
+                            -90 <= top <= 90 and
+                            -90 <= bottom <= 90):
+                        text = _("Select layer '%s' and pick a projection "
+                                 "using Layer/Projection...") % layer.title
+                        break
+
+        self.set_position_text(text)
+
+    def set_position_text(self, text):
+        """Set the statusbar text to that created by update_status_bar
+
+        By default the text is shown in field 0 of the status bar.
+        Override this method in derived classes to put it into a
+        different field of the statusbar.
+
+        For historical reasons this method is called set_position_text
+        because at first the text was always either the current position
+        or the empty string.  Now it can contain other messages as well.
+        The method will be renamed at one point.
+        """
+        # Note: If this method is renamed we should perhaps think about
+        # some backwards compatibility measures for projects like
+        # GREAT-ER which override this method.
+        self.SetStatusText(text)
+
+    def OpenOrRaiseDialog(self, name, dialog_class, *args, **kw):
+        """
+        Open or raise a dialog.
+
+        If a dialog with the denoted name does already exist it is
+        raised.  Otherwise a new dialog, an instance of dialog_class,
+        is created, inserted into the main list and displayed.
+        """
+        dialog = self.get_open_dialog(name)
+
+        if dialog is None:
+            dialog = dialog_class(self, name, *args, **kw)
+            self.add_dialog(name, dialog)
+            dialog.Show(True)
+        else:
+            dialog.Raise()
+
+    def save_modified_session(self, can_veto = 1):
+        """If the current session has been modified, ask the user
+        whether to save it and do so if requested. Return the outcome of
+        the dialog (either wxID_OK, wxID_CANCEL or wxID_NO). If the
+        dialog wasn't run return wxID_NO.
+
+        If the can_veto parameter is true (default) the dialog includes
+        a cancel button, otherwise not.
+        """
+        if self.application.session.WasModified():
+            flags = wx.YES_NO | wx.ICON_QUESTION
+            if can_veto:
+                flags = flags | wx.CANCEL
+            result = self.RunMessageBox(_("Exit"),
+                                        _("The session has been modified."
+                                         " Do you want to save it?"),
+                                        flags)
+            if result == wx.ID_YES:
+                self.SaveSession()
+        else:
+            result = wx.ID_NO
+        return result
+
+    def NewSession(self):
+        if self.save_modified_session() != wx.ID_CANCEL:
+            self.application.SetSession(create_empty_session())
+
+    def OpenSession(self):
+        if self.save_modified_session() != wx.ID_CANCEL:
+            dlg = wx.FileDialog(self, _("Open Session"),
+                               self.application.Path("data"), "",
+                               "Thuban Session File (*.thuban)|*.thuban",
+                               wx.OPEN)
+            if dlg.ShowModal() == wx.ID_OK:
+                self.application.OpenSession(dlg.GetPath(),
+                                             self.run_db_param_dialog)
+                self.application.SetPath("data", dlg.GetPath())
+            dlg.Destroy()
+
+    def run_db_param_dialog(self, parameters, message):
+        dlg = DBDialog(self, _("DB Connection Parameters"), parameters,
+                       message)
+        return dlg.RunDialog()
+
+    def SaveSession(self):
+        if self.application.session.filename == None:
+            self.SaveSessionAs()
+        else:
+            self.application.SaveSession()
+
+    def SaveSessionAs(self):
+        dlg = wx.FileDialog(self, _("Save Session As"),
+                           self.application.Path("data"), "",
+                           "Thuban Session File (*.thuban)|*.thuban",
+                           wx.SAVE|wx.OVERWRITE_PROMPT)
+        if dlg.ShowModal() == wx.ID_OK:
+            self.application.session.SetFilename(dlg.GetPath())
+            self.application.SaveSession()
+            self.application.SetPath("data",dlg.GetPath())
+        dlg.Destroy()
+
+    def Exit(self):
+        self.Close(False)
+
+    def OnClose(self, event):
+        result = self.save_modified_session(can_veto = event.CanVeto())
+        if result == wx.ID_CANCEL:
+            event.Veto()
+        else:
+            # FIXME: it would be better to tie the unsubscription to
+            # wx's destroy event, but that isn't implemented for wxGTK
+            # yet.
+            for channel in self.update_status_bar_messages:
+                self.canvas.Unsubscribe(channel, self.update_status_bar)
+
+            DockFrame.OnClose(self, event)
+            for dlg in self.dialogs.values():
+                dlg.Destroy()
+            self.canvas.Destroy()
+            self.Destroy()
+
+    def SetMap(self, map):
+        self.canvas.SetMap(map)
+        self.update_title()
+
+        dialog = self.FindRegisteredDock("legend")
+        if dialog is not None:
+            dialog.GetPanel().SetMap(self.Map())
+
+    def Map(self):
+        """Return the map displayed by this mainwindow"""
+
+        return self.canvas.Map()
+
+    def ToggleSessionTree(self):
+        """If the session tree is shown close it otherwise create a new tree"""
+        name = "session_tree"
+        dialog = self.get_open_dialog(name)
+        if dialog is None:
+            dialog = tree.SessionTreeView(self, self.application, name)
+            self.add_dialog(name, dialog)
+            dialog.Show(True)
+        else:
+            dialog.Close()
+
+    def SessionTreeShown(self):
+        """Return true iff the session tree is currently shown"""
+        return self.get_open_dialog("session_tree") is not None
+
+    def About(self):
+        dlg = About(self)
+        dlg.ShowModal()
+        dlg.Destroy()
+
+    def DatabaseManagement(self):
+        name = "dbmanagement"
+        dialog = self.get_open_dialog(name)
+        if dialog is None:
+            map = self.canvas.Map()
+            dialog = DBFrame(self, name, self.application.Session())
+            self.add_dialog(name, dialog)
+            dialog.Show()
+        dialog.Raise()
+
+    def AddLayer(self):
+        dlg = wx.FileDialog(self, _("Select one or more data files"),
+                           self.application.Path("data"), "",
+                           _("Shapefiles (*.shp)") + "|*.shp;*.SHP|" +
+                           _("All Files (*.*)") + "|*.*",
+                           wx.OPEN | wx.MULTIPLE)
+        if dlg.ShowModal() == wx.ID_OK:
+            filenames = dlg.GetPaths()
+            for filename in filenames:
+                title = os.path.splitext(os.path.basename(filename))[0]
+                map = self.canvas.Map()
+                has_layers = map.HasLayers()
+                try:
+                    store = self.application.Session().OpenShapefile(filename)
+                except IOError:
+                    # the layer couldn't be opened
+                    self.RunMessageBox(_("Add Layer"),
+                                       _("Can't open the file '%s'.")%filename)
+                else:
+                    layer = Layer(title, store)
+                    map.AddLayer(layer)
+                    if not has_layers:
+                        # if we're adding a layer to an empty map, fit the
+                        # new map to the window
+                        self.canvas.FitMapToWindow()
+                    self.application.SetPath("data",filename)
+        dlg.Destroy()
+
+    def AddRasterLayer(self):
+        dlg = wx.FileDialog(self, _("Select an image file"),
+                           self.application.Path("data"), "", "*.*",
+                           wx.OPEN)
+        if dlg.ShowModal() == wx.ID_OK:
+            filename = dlg.GetPath()
+            title = os.path.splitext(os.path.basename(filename))[0]
+            map = self.canvas.Map()
+            has_layers = map.HasLayers()
+            try:
+                layer = RasterLayer(title, filename)
+            except IOError:
+                # the layer couldn't be opened
+                self.RunMessageBox(_("Add Image Layer"),
+                                   _("Can't open the file '%s'.") % filename)
+            else:
+                map.AddLayer(layer)
+                if not has_layers:
+                    # if we're adding a layer to an empty map, fit the
+                    # new map to the window
+                    self.canvas.FitMapToWindow()
+                self.application.SetPath("data", filename)
+        dlg.Destroy()
+
+    def AddDBLayer(self):
+        """Add a layer read from a database"""
+        session = self.application.Session()
+        dlg = ChooseDBTableDialog(self, self.application.Session())
+
+        if dlg.ShowModal() == wx.ID_OK:
+            dbconn, dbtable, id_column, geo_column = dlg.GetTable()
+            try:
+                title = str(dbtable)
+
+                # Chose the correct Interface for the database type
+                store = session.OpenDBShapeStore(dbconn, dbtable,
+                                                 id_column = id_column,
+                                                 geometry_column = geo_column)
+                layer = Layer(title, store)
+            except:
+                # Some error occured while initializing the layer
+                self.RunMessageBox(_("Add Layer from database"),
+                                   _("Can't open the database table '%s'")
+                                   % dbtable)
+                return
+
+            map = self.canvas.Map()
+
+            has_layers = map.HasLayers()
+            map.AddLayer(layer)
+            if not has_layers:
+                self.canvas.FitMapToWindow()
+
+        dlg.Destroy()
+
+    def RemoveLayer(self):
+        layer = self.current_layer()
+        if layer is not None:
+            self.canvas.Map().RemoveLayer(layer)
+
+    def CanRemoveLayer(self):
+        """Return true if the currently selected layer can be deleted.
+
+        If no layer is selected return False.
+
+        The return value of this method determines whether the remove
+        layer command is sensitive in menu.
+        """
+        layer = self.current_layer()
+        if layer is not None:
+            return self.canvas.Map().CanRemoveLayer(layer)
+        return False
+
+    def LayerToTop(self):
+        layer = self.current_layer()
+        if layer is not None:
+            self.canvas.Map().MoveLayerToTop(layer)
+
+    def RaiseLayer(self):
+        layer = self.current_layer()
+        if layer is not None:
+            self.canvas.Map().RaiseLayer(layer)
+
+    def LowerLayer(self):
+        layer = self.current_layer()
+        if layer is not None:
+            self.canvas.Map().LowerLayer(layer)
+
+    def LayerToBottom(self):
+        layer = self.current_layer()
+        if layer is not None:
+            self.canvas.Map().MoveLayerToBottom(layer)
+
+    def current_layer(self):
+        """Return the currently selected layer.
+
+        If no layer is selected, return None
+        """
+        return self.canvas.SelectedLayer()
+
+    def has_selected_layer(self):
+        """Return true if a layer is currently selected"""
+        return self.canvas.HasSelectedLayer()
+
+    def has_selected_shape_layer(self):
+        """Return true if a shape layer is currently selected"""
+        return isinstance(self.current_layer(), Layer)
+
+    def has_selected_shapes(self):
+        """Return true if a shape is currently selected"""
+        return self.canvas.HasSelectedShapes()
+
+    def HideLayer(self):
+        layer = self.current_layer()
+        if layer is not None:
+            layer.SetVisible(False)
+
+    def ShowLayer(self):
+        layer = self.current_layer()
+        if layer is not None:
+            layer.SetVisible(True)
+
+    def ToggleLayerVisibility(self):
+        layer = self.current_layer()
+        layer.SetVisible(not layer.Visible())
+
+    def DuplicateLayer(self):
+        """Ceate a new layer above the selected layer with the same shapestore
+        """
+        layer = self.current_layer()
+        if layer is not None and hasattr(layer, "ShapeStore"):
+            new_layer = Layer(_("Copy of `%s'") % layer.Title(),
+                              layer.ShapeStore(),
+                              projection = layer.GetProjection())
+            new_classification = copy.deepcopy(layer.GetClassification())
+            new_layer.SetClassificationColumn(
+                    layer.GetClassificationColumn())
+            new_layer.SetClassification(new_classification)
+            self.Map().AddLayer(new_layer)
+
+    def CanDuplicateLayer(self):
+        """Return whether the DuplicateLayer method can create a duplicate"""
+        layer = self.current_layer()
+        return layer is not None and hasattr(layer, "ShapeStore")
+
+    def LayerShowTable(self):
+        """
+        Present a TableView Window for the current layer.
+        In case the window is already open, bring it to the front.
+        In case, there is no active layer, do nothing.
+        In case, the layer has no ShapeStore, do nothing.
+        """
+        layer = self.current_layer()
+        if layer is not None:
+            if not hasattr(layer, "ShapeStore"):
+                return
+            table = layer.ShapeStore().Table()
+            name = "table_view" + str(id(table))
+            dialog = self.get_open_dialog(name)
+            if dialog is None:
+                dialog = tableview.LayerTableFrame(self, name,
+                                         _("Layer Table: %s") % layer.Title(),
+                                         layer, table)
+                self.add_dialog(name, dialog)
+                dialog.Show(True)
+            else:
+                dialog.Raise()
+
+    def MapProjection(self):
+
+        name = "map_projection"
+        dialog = self.get_open_dialog(name)
+
+        if dialog is None:
+            map = self.canvas.Map()
+            dialog = projdialog.ProjFrame(self, name,
+                     _("Map Projection: %s") % map.Title(), map)
+            self.add_dialog(name, dialog)
+            dialog.Show()
+        dialog.Raise()
+
+    def LayerProjection(self):
+
+        layer = self.current_layer()
+
+        name = "layer_projection" + str(id(layer))
+        dialog = self.get_open_dialog(name)
+
+        if dialog is None:
+            map = self.canvas.Map()
+            dialog = projdialog.ProjFrame(self, name,
+                     _("Layer Projection: %s") % layer.Title(), layer)
+            self.add_dialog(name, dialog)
+            dialog.Show()
+        dialog.Raise()
+
+    def LayerEditProperties(self):
+
+        #
+        # the menu option for this should only be available if there
+        # is a current layer, so we don't need to check if the 
+        # current layer is None
+        #
+
+        layer = self.current_layer()
+        self.OpenLayerProperties(layer)
+
+    def OpenLayerProperties(self, layer, group = None):
+        """
+        Open or raise the properties dialog.
+
+        This method opens or raises the properties dialog for the
+        currently selected layer if one is defined for this layer
+        type.
+        """
+        dialog_class = layer_properties_dialogs.get(layer)
+
+        if dialog_class is not None:
+            name = "layer_properties" + str(id(layer))
+            self.OpenOrRaiseDialog(name, dialog_class, layer, group = group)
+
+    def LayerJoinTable(self):
+        layer = self.canvas.SelectedLayer()
+        if layer is not None:
+            dlg = JoinDialog(self, _("Join Layer with Table"),
+                             self.application.session,
+                             layer = layer)
+            dlg.ShowModal()
+
+    def LayerUnjoinTable(self):
+        layer = self.canvas.SelectedLayer()
+        if layer is not None:
+            orig_store = layer.ShapeStore().OrigShapeStore()
+            if orig_store:
+                layer.SetShapeStore(orig_store)
+
+    def ShowLegend(self):
+        if not self.LegendShown():
+            self.ToggleLegend()
+
+    def ToggleLegend(self):
+        """Show the legend if it's not shown otherwise hide it again"""
+        name = "legend"
+        dialog = self.FindRegisteredDock(name)
+
+        if dialog is None:
+            dialog = self.CreateDock(name, -1, _("Legend"), wx.LAYOUT_LEFT)
+            legend.LegendPanel(dialog, None, self)
+            dialog.Dock()
+            dialog.GetPanel().SetMap(self.Map())
+            dialog.Show()
+        else:
+            dialog.Show(not dialog.IsShown())
+
+    def LegendShown(self):
+        """Return true iff the legend is currently open"""
+        dialog = self.FindRegisteredDock("legend")
+        return dialog is not None and dialog.IsShown()
+
+    def TableOpen(self):
+        dlg = wx.FileDialog(self, _("Open Table"),
+                           self.application.Path("data"), "",
+                           _("DBF Files (*.dbf)") + "|*.dbf|" +
+                           #_("CSV Files (*.csv)") + "|*.csv|" + 
+                           _("All Files (*.*)") + "|*.*",
+                           wx.OPEN)
+        if dlg.ShowModal() == wx.ID_OK:
+            filename = dlg.GetPath()
+            dlg.Destroy()
+            try:
+                table = self.application.session.OpenTableFile(filename)
+            except IOError:
+                # the layer couldn't be opened
+                self.RunMessageBox(_("Open Table"),
+                                   _("Can't open the file '%s'.") % filename)
+            else:
+                self.ShowTableView(table)
+                self.application.SetPath("data",filename)
+
+    def TableClose(self):
+        tables = self.application.session.UnreferencedTables()
+
+        lst = [(t.Title(), t) for t in tables]
+        lst.sort()
+        titles = [i[0] for i in lst]
+        dlg = MultipleChoiceDialog(self, _("Pick the tables to close:"),
+                                     _("Close Table"), titles,
+                                     size = (400, 300),
+                                     style = wx.DEFAULT_DIALOG_STYLE |
+                                             wx.RESIZE_BORDER)
+        if dlg.ShowModal() == wx.ID_OK:
+            for i in dlg.GetValue():
+                self.application.session.RemoveTable(lst[i][1])
+
+
+    def TableShow(self):
+        """Offer a multi-selection dialog for tables to be displayed
+
+        The windows for the selected tables are opened or brought to
+        the front.
+        """
+        tables = self.application.session.Tables()
+
+        lst = [(t.Title(), t) for t in tables]
+        lst.sort()
+        titles = [i[0] for i in lst]
+        dlg = MultipleChoiceDialog(self, _("Pick the table to show:"),
+                                     _("Show Table"), titles,
+                                     size = (400,300),
+                                     style = wx.DEFAULT_DIALOG_STYLE |
+                                             wx.RESIZE_BORDER)
+        if (dlg.ShowModal() == wx.ID_OK):
+            for i in dlg.GetValue():
+                # XXX: if the table belongs to a layer, open a
+                # LayerTableFrame instead of QueryTableFrame
+                self.ShowTableView(lst[i][1])
+
+    def TableJoin(self):
+        dlg = JoinDialog(self, _("Join Tables"), self.application.session)
+        dlg.ShowModal()
+
+    def ShowTableView(self, table):
+        """Open a table view for the table and optionally"""
+        name = "table_view%d" % id(table)
+        dialog = self.get_open_dialog(name)
+        if dialog is None:
+            dialog = tableview.QueryTableFrame(self, name,
+                                               _("Table: %s") % table.Title(),
+                                               table)
+            self.add_dialog(name, dialog)
+            dialog.Show(True)
+        dialog.Raise()
+
+    def TableRename(self):
+        """Let the user rename a table"""
+
+        # First, let the user select a table
+        tables = self.application.session.Tables()
+        lst = [(t.Title(), t) for t in tables]
+        lst.sort()
+        titles = [i[0] for i in lst]
+        dlg = MultipleChoiceDialog(self, _("Pick the table to rename:"),
+                                     _("Rename Table"), titles,
+                                     size = (400,300),
+                                     style = wx.DEFAULT_DIALOG_STYLE |
+                                             wx.RESIZE_BORDER)
+        if (dlg.ShowModal() == wx.ID_OK):
+            to_rename = [lst[i][1] for i in dlg.GetValue()]
+            dlg.Destroy()
+        else:
+            to_rename = []
+
+        # Second, let the user rename the layers
+        for table in to_rename:
+            dlg = wx.TextEntryDialog(self, _("Table Title:"), _("Rename Table"),
+                                    table.Title())
+            try:
+                if dlg.ShowModal() == wx.ID_OK:
+                    title = dlg.GetValue()
+                    if title != "":
+                        table.SetTitle(title)
+
+                        # Make sure the session is marked as modified.
+                        # FIXME: This should be handled automatically,
+                        # but that requires more changes to the tables
+                        # than I have time for currently.
+                        self.application.session.changed()
+            finally:
+                dlg.Destroy()
+
+
+    def ZoomInTool(self):
+        self.canvas.ZoomInTool()
+
+    def ZoomOutTool(self):
+        self.canvas.ZoomOutTool()
+
+    def PanTool(self):
+        self.canvas.PanTool()
+
+    def IdentifyTool(self):
+        self.canvas.IdentifyTool()
+        self.identify_view_on_demand(None, None)
+
+    def LabelTool(self):
+        self.canvas.LabelTool()
+
+    def FullExtent(self):
+        self.canvas.FitMapToWindow()
+
+    def FullLayerExtent(self):
+        self.canvas.FitLayerToWindow(self.current_layer())
+
+    def FullSelectionExtent(self):
+        self.canvas.FitSelectedToWindow()
+
+    def ExportMap(self):
+        self.canvas.Export()
+
+    def PrintMap(self):
+        self.canvas.Print()
+
+    def RenameMap(self):
+        dlg = wx.TextEntryDialog(self, _("Map Title:"), _("Rename Map"),
+                                self.Map().Title())
+        if dlg.ShowModal() == wx.ID_OK:
+            title = dlg.GetValue()
+            if title != "":
+                self.Map().SetTitle(title)
+
+        dlg.Destroy()
+
+    def RenameLayer(self):
+        """Let the user rename the currently selected layer"""
+        layer = self.current_layer()
+        if layer is not None:
+            dlg = wx.TextEntryDialog(self, _("Layer Title:"), _("Rename Layer"),
+                                    layer.Title())
+            try:
+                if dlg.ShowModal() == wx.ID_OK:
+                    title = dlg.GetValue()
+                    if title != "":
+                        layer.SetTitle(title)
+            finally:
+                dlg.Destroy()
+
+    def identify_view_on_demand(self, layer, shapes):
+        """Subscribed to the canvas' SHAPES_SELECTED message
+
+        If the current tool is the identify tool, at least one shape is
+        selected and the identify dialog is not shown, show the dialog.
+        """
+        # If the selection has become empty we don't need to do
+        # anything. Otherwise it could happen that the dialog was popped
+        # up when the selection became empty, e.g. when a new selection
+        # is opened while the identify tool is active and dialog had
+        # been closed
+        if not shapes:
+            return
+
+        name = "identify_view"
+        if self.canvas.CurrentTool() == "IdentifyTool":
+            if not self.dialog_open(name):
+                dialog = identifyview.IdentifyView(self, name)
+                self.add_dialog(name, dialog)
+                dialog.Show(True)
+            else:
+                # FIXME: bring dialog to front?
+                pass
+
+    def title_changed(self, map):
+        """Subscribed to the canvas' TITLE_CHANGED messages"""
+        self.update_title()
+
+    def update_title(self):
+        """Update the window's title according to it's current state.
+
+        In this default implementation the title is 'Thuban - ' followed
+        by the map's title or simply 'Thuban' if there is not map.
+        Derived classes should override this method to get different
+        titles.
+
+        This method is called automatically by other methods when the
+        title may have to change. For the methods implemented in this
+        class this usually only means that a different map has been set
+        or the current map's title has changed.
+        """
+        map = self.Map()
+        if map is not None:
+            title = _("Thuban - %s") % (map.Title(),)
+        else:
+            title = _("Thuban")
+        self.SetTitle(title)
+
+
+#
+# Define all the commands available in the main window
+#
+
+
+# Helper functions to define common command implementations
+def call_method(context, methodname, *args):
+    """Call the mainwindow's method methodname with args *args"""
+    apply(getattr(context.mainwindow, methodname), args)
+
+def _method_command(name, title, method, helptext = "",
+                    icon = "", sensitive = None, checked = None):
+    """Add a command implemented by a method of the mainwindow object"""
+    registry.Add(Command(name, title, call_method, args=(method,),
+                         helptext = helptext, icon = icon,
+                         sensitive = sensitive, checked = checked))
+
+def make_check_current_tool(toolname):
+    """Return a function that tests if the currently active tool is toolname
+
+    The returned function can be called with the context and returns
+    true iff the currently active tool's name is toolname. It's directly
+    usable as the 'checked' callback of a command.
+    """
+    def check_current_tool(context, name=toolname):
+        return context.mainwindow.canvas.CurrentTool() == name
+    return check_current_tool
+
+def _tool_command(name, title, method, toolname, helptext = "",
+                  icon = "", sensitive = None):
+    """Add a tool command"""
+    registry.Add(ToolCommand(name, title, call_method, args=(method,),
+                             helptext = helptext, icon = icon,
+                             checked = make_check_current_tool(toolname),
+                             sensitive = sensitive))
+
+def _has_selected_layer(context):
+    """Return true if a layer is selected in the context"""
+    return context.mainwindow.has_selected_layer()
+
+def _has_selected_layer_visible(context):
+    """Return true if a layer is selected in the context which is
+    visible."""
+    if context.mainwindow.has_selected_layer():
+        layer = context.mainwindow.current_layer()
+        if layer.Visible(): return True
+    return False
+
+def _has_selected_shape_layer(context):
+    """Return true if a shape layer is selected in the context"""
+    return context.mainwindow.has_selected_shape_layer()
+
+def _has_selected_shapes(context):
+    """Return true if a layer is selected in the context"""
+    return context.mainwindow.has_selected_shapes()
+
+def _can_remove_layer(context):
+    return context.mainwindow.CanRemoveLayer()
+
+def _has_tree_window_shown(context):
+    """Return true if the tree window is shown"""
+    return context.mainwindow.SessionTreeShown()
+
+def _has_visible_map(context):
+    """Return true iff theres a visible map in the mainwindow.
+
+    A visible map is a map with at least one visible layer."""
+    map = context.mainwindow.Map()
+    if map is not None:
+        for layer in map.Layers():
+            if layer.Visible():
+                return True
+    return False
+
+def _has_legend_shown(context):
+    """Return true if the legend window is shown"""
+    return context.mainwindow.LegendShown()
+
+def _has_gdal_support(context):
+    """Return True if the GDAL is available"""
+    return Thuban.Model.resource.has_gdal_support()
+
+def _has_dbconnections(context):
+    """Return whether the the session has database connections"""
+    return context.session.HasDBConnections()
+
+def _has_postgis_support(context):
+    return has_postgis_support()
+
+
+# File menu
+_method_command("new_session", _("&New Session"), "NewSession",
+                helptext = _("Start a new session"))
+_method_command("open_session", _("&Open Session..."), "OpenSession",
+                helptext = _("Open a session file"))
+_method_command("save_session", _("&Save Session"), "SaveSession",
+                helptext =_("Save this session to the file it was opened from"))
+_method_command("save_session_as", _("Save Session &As..."), "SaveSessionAs",
+                helptext = _("Save this session to a new file"))
+_method_command("toggle_session_tree", _("Session &Tree"), "ToggleSessionTree",
+                checked = _has_tree_window_shown,
+                helptext = _("Toggle on/off the session tree analysis window"))
+_method_command("toggle_legend", _("Legend"), "ToggleLegend",
+                checked = _has_legend_shown,
+                helptext = _("Toggle Legend on/off"))
+_method_command("database_management", _("&Database Connections..."),
+                "DatabaseManagement",
+                sensitive = _has_postgis_support)
+_method_command("exit", _("E&xit"), "Exit",
+                helptext = _("Finish working with Thuban"))
+
+# Help menu
+_method_command("help_about", _("&About..."), "About",
+                helptext = _("Info about Thuban authors, version and modules"))
+
+
+# Map menu
+_method_command("map_projection", _("Pro&jection..."), "MapProjection",
+                helptext = _("Set or change the map projection"))
+
+_tool_command("map_zoom_in_tool", _("&Zoom in"), "ZoomInTool", "ZoomInTool",
+              helptext = _("Switch to map-mode 'zoom-in'"), icon = "zoom_in",
+              sensitive = _has_visible_map)
+_tool_command("map_zoom_out_tool", _("Zoom &out"), "ZoomOutTool", "ZoomOutTool",
+              helptext = _("Switch to map-mode 'zoom-out'"), icon = "zoom_out",
+              sensitive = _has_visible_map)
+_tool_command("map_pan_tool", _("&Pan"), "PanTool", "PanTool",
+              helptext = _("Switch to map-mode 'pan'"), icon = "pan",
+              sensitive = _has_visible_map)
+_tool_command("map_identify_tool", _("&Identify"), "IdentifyTool",
+              "IdentifyTool",
+              helptext = _("Switch to map-mode 'identify'"), icon = "identify",
+              sensitive = _has_visible_map)
+_tool_command("map_label_tool", _("&Label"), "LabelTool", "LabelTool",
+              helptext = _("Add/Remove labels"), icon = "label",
+              sensitive = _has_visible_map)
+_method_command("map_full_extent", _("&Full extent"), "FullExtent",
+               helptext = _("Zoom to the full map extent"), icon = "fullextent",
+              sensitive = _has_visible_map)
+_method_command("layer_full_extent", _("&Full layer extent"), "FullLayerExtent",
+                helptext = _("Zoom to the full layer extent"),
+                icon = "fulllayerextent", sensitive = _has_selected_layer)
+_method_command("selected_full_extent", _("&Full selection extent"),
+                "FullSelectionExtent",
+                helptext = _("Zoom to the full selection extent"),
+                icon = "fullselextent", sensitive = _has_selected_shapes)
+_method_command("map_export", _("E&xport"), "ExportMap",
+                helptext = _("Export the map to file"))
+_method_command("map_print", _("Prin&t"), "PrintMap",
+                helptext = _("Print the map"))
+_method_command("map_rename", _("&Rename..."), "RenameMap",
+                helptext = _("Rename the map"))
+_method_command("layer_add", _("&Add Layer..."), "AddLayer",
+                helptext = _("Add a new layer to the map"))
+_method_command("rasterlayer_add", _("&Add Image Layer..."), "AddRasterLayer",
+                helptext = _("Add a new image layer to the map"),
+                sensitive = _has_gdal_support)
+_method_command("layer_add_db", _("Add &Database Layer..."), "AddDBLayer",
+                helptext = _("Add a new database layer to active map"),
+                sensitive = _has_dbconnections)
+_method_command("layer_remove", _("&Remove Layer"), "RemoveLayer",
+                helptext = _("Remove selected layer"),
+                sensitive = _can_remove_layer)
+
+# Layer menu
+_method_command("layer_projection", _("Pro&jection..."), "LayerProjection",
+                sensitive = _has_selected_layer,
+                helptext = _("Specify projection for selected layer"))
+_method_command("layer_duplicate", _("&Duplicate"), "DuplicateLayer",
+                helptext = _("Duplicate selected layer"),
+          sensitive = lambda context: context.mainwindow.CanDuplicateLayer())
+_method_command("layer_rename", _("Re&name ..."), "RenameLayer",
+                helptext = _("Rename selected layer"),
+                sensitive = _has_selected_layer)
+_method_command("layer_raise", _("&Raise"), "RaiseLayer",
+                helptext = _("Raise selected layer"),
+                sensitive = _has_selected_layer)
+_method_command("layer_lower", _("&Lower"), "LowerLayer",
+                helptext = _("Lower selected layer"),
+                sensitive = _has_selected_layer)
+_method_command("layer_show", _("&Show"), "ShowLayer",
+                helptext = _("Make selected layer visible"),
+                sensitive = _has_selected_layer)
+_method_command("layer_hide", _("&Hide"), "HideLayer",
+                helptext = _("Make selected layer unvisible"),
+                sensitive = _has_selected_layer)
+_method_command("layer_show_table", _("Show Ta&ble"), "LayerShowTable",
+                helptext = _("Show the selected layer's table"),
+                sensitive = _has_selected_shape_layer)
+_method_command("layer_properties", _("&Properties..."), "LayerEditProperties",
+                sensitive = _has_selected_layer,
+                helptext = _("Edit the properties of the selected layer"))
+_method_command("layer_jointable", _("&Join Table..."), "LayerJoinTable",
+                sensitive = _has_selected_shape_layer,
+                helptext = _("Join and attach a table to the selected layer"))
+
+# further layer methods:
+_method_command("layer_to_top", _("&Top"), "LayerToTop",
+                helptext = _("Put selected layer to the top"),
+                sensitive = _has_selected_layer)
+_method_command("layer_to_bottom", _("&Bottom"), "LayerToBottom",
+                helptext = _("Put selected layer to the bottom"),
+                sensitive = _has_selected_layer)
+_method_command("layer_visibility", _("&Visible"), "ToggleLayerVisibility",
+                checked = _has_selected_layer_visible,
+                helptext = _("Toggle visibility of selected layer"),
+                sensitive = _has_selected_layer)
+
+def _can_unjoin(context):
+    """Return whether the Layer/Unjoin command can be executed.
+
+    This is the case if a layer is selected and that layer has a
+    shapestore that has an original shapestore.
+    """
+    layer = context.mainwindow.SelectedLayer()
+    if layer is None:
+        return 0
+    getstore = getattr(layer, "ShapeStore", None)
+    if getstore is not None:
+        return getstore().OrigShapeStore() is not None
+    else:
+        return 0
+_method_command("layer_unjointable", _("&Unjoin Table..."), "LayerUnjoinTable",
+                sensitive = _can_unjoin,
+                helptext = _("Undo the last join operation"))
+
+
+def _has_tables(context):
+    return bool(context.session.Tables())
+
+# Table menu
+_method_command("table_open", _("&Open..."), "TableOpen",
+                helptext = _("Open a DBF-table from a file"))
+_method_command("table_close", _("&Close..."), "TableClose",
+       sensitive = lambda context: bool(context.session.UnreferencedTables()),
+                helptext = _("Close one or more tables from a list"))
+_method_command("table_rename", _("&Rename..."), "TableRename",
+                sensitive = _has_tables,
+                helptext = _("Rename one or more tables"))
+_method_command("table_show", _("&Show..."), "TableShow",
+                sensitive = _has_tables,
+                helptext = _("Show one or more tables in a dialog"))
+_method_command("table_join", _("&Join..."), "TableJoin",
+                sensitive = _has_tables,
+                helptext = _("Join two tables creating a new one"))
+
+#  Export only under Windows ...
+map_menu = ["layer_add", "layer_add_db", "rasterlayer_add", "layer_remove",
+                        None,
+                        "map_rename",
+                        "map_projection",
+                        None,
+                        "map_zoom_in_tool", "map_zoom_out_tool",
+                        "map_pan_tool",
+                        "map_full_extent",
+                        "layer_full_extent",
+                        "selected_full_extent",
+                        None,
+                        "map_identify_tool", "map_label_tool",
+                        None,
+                        "toggle_legend",
+                        None]
+if wx.Platform == '__WXMSW__':
+    map_menu.append("map_export")
+map_menu.append("map_print")
+
+# the menu structure
+main_menu = Menu("<main>", "<main>",
+                 [Menu("file", _("&File"),
+                       ["new_session", "open_session", None,
+                        "save_session", "save_session_as", None,
+                        "database_management", None,
+                        "toggle_session_tree", None,
+                        "exit"]),
+                  Menu("map", _("&Map"), map_menu),
+                  Menu("layer", _("&Layer"),
+                       ["layer_rename", "layer_duplicate",
+                        None,
+                        "layer_raise", "layer_lower",
+                        None,
+                        "layer_show", "layer_hide",
+                        None,
+                        "layer_projection",
+                        None,
+                        "layer_show_table",
+                        "layer_jointable",
+                        "layer_unjointable",
+                        None,
+                        "layer_properties"]),
+                  Menu("table", _("&Table"),
+                       ["table_open", "table_close", "table_rename",
+                       None,
+                       "table_show",
+                       None,
+                       "table_join"]),
+                  Menu("help", _("&Help"),
+                       ["help_about"])])
+
+# the main toolbar
+
+main_toolbar = Menu("<toolbar>", "<toolbar>",
+                    ["map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",
+                     "map_full_extent",
+                     "layer_full_extent",
+                     "selected_full_extent",
+                     None,
+                     "map_identify_tool", "map_label_tool"])
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/menu.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/menu.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/menu.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,154 @@
+# Copyright (C) 2001, 2002 by Intevation GmbH
+# Author:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Menu management"""
+
+__version__ = "$Revision: 2202 $"
+
+from Thuban import _
+
+class Menu:
+
+    """Represent a menu or submenu.
+
+    A menu has a name and a title. The name can be used to identify
+    menus internally while the title is intended for use in the GUI.
+
+    Menu items can be added with the Insert* methods.
+    """
+
+    def __init__(self, name, title, items = None):
+        """Initialize the menu.
+
+        Parameters:
+           name -- the name of the menu
+           title -- the (possibly localized) title of the menu
+           items -- (optional) a list of menu items.
+
+        The items list may contains strings with command names, None to
+        indicate separators or Menu instances for submenus.
+        """
+        self.name = name
+        self.title = title
+        if items is None:
+            self.items = []
+        else:
+            self.items = items
+
+    def item_index(self, item):
+        """Return the index of item in the menu.
+
+        item -- may be the name of a non-menu entry or the
+                name of a menu or a menu itself.
+
+        Return None it item is not found.
+        """
+        for i in range(len(self.items)):
+            temp = self.items[i]
+            if temp == item:
+                # this case takes care of item being the name of an
+                # entry or a menu.
+                return i
+            elif isinstance(temp, Menu) and temp.name == item:
+                # item is the name of a menu
+                return i
+        # Didn't find the item so return None
+        return None
+
+    def find_menu(self, name):
+        """Return the submenu named name or None if no such item exists"""
+        for item in self.items:
+            if isinstance(item, Menu) and item.name == name:
+                return item
+        return None
+
+    def InsertItem(self, item, menu = (), after = None):
+        """Insert a menu item.
+
+        Parameters:
+
+         item -- the menu item to insert must be either a string with
+                the command's name or a Menu instance.
+
+         menu -- (optional) the submenu to insert into. It should be a
+                sequence of menu names.
+
+         after -- (optional) insert the new item after this one. after
+                 should be the name of a command.
+        """
+        # if menu is given, get the first submenu
+        if menu:
+            submenu_index = self.find_menu(menu[0])
+            if submenu_index is not None:
+                submenu_index.InsertItem(item, menu = menu[1:], after = after)
+            else:
+                # the submenu doesn't exist yet. Raise an error.
+                raise KeyError(_("Submenu %s doesn't exist") % menu[0])
+        else:
+            if after is not None:
+                idx = self.item_index(after)
+            else:
+                idx = None
+
+            if idx is not None:
+                self.items.insert(idx + 1, item)
+            else:
+                self.items.append(item)
+
+    def InsertSeparator(self, after = None):
+        """Insert a separator
+
+        after -- (optional) insert the separator after this one. after
+                 should be the name of a command.
+        """
+        self.InsertItem(None, after = after)
+
+    def InsertMenu(self, name, title, menu = (), after = None):
+        """Insert and return a new menu.
+
+        Parameters:
+
+         name -- the (internal) name of the menu
+
+         title -- the (possibly localized) title
+
+         menu -- (optional) the submenu to insert into. It should be a
+                sequence of menu names.
+
+         after -- (optional) insert the new item after this one. after
+                 should be the name of a command.
+        """
+        newmenu = Menu(name, title)
+        self.InsertItem(newmenu, menu = menu, after = after)
+        return newmenu
+
+    def FindOrInsertMenu(self, name, title, menu = (), after = None):
+        """
+        Find the menu with the specified name. If found, return it.
+        Else insert the menu as specified and return it.
+
+        Parameters: See InsertMenu().
+        """
+
+        m = self.find_menu(name)
+        if m is None:
+            m = self.InsertMenu(name, title, menu, after)
+        return m
+
+
+    def SetItems(self, items):
+        """Replace the contents of the menu by items."""
+        self.items = items
+
+    def RemoveItem(self, item):
+        """Remove an item from the menu.
+
+        item -- the (internal) name of the item.
+        """
+        i = self.item_index(item)
+        if i is not None:
+            self.items.pop(i)

Added: packages/thuban/branches/upstream/current/Thuban/UI/messages.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/messages.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/messages.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,36 @@
+# Copyright (c) 2001, 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+
+"""
+Define the message types used in Thuban's GUI. The messages types are
+simply strings. The message system itself is implemented in
+Thuban.Lib.connector.
+"""
+
+__version__ = "$Revision: 1464 $"
+
+# Application object
+SESSION_REPLACED = "SESSION_REPLACED"
+
+# events for the selection
+LAYER_SELECTED = "LAYER_SELECTED"
+SHAPES_SELECTED = "SHAPES_SELECTED"
+# obsolete selection messages.
+SELECTED_SHAPE = "SELECTED_SHAPE"
+SELECTED_LAYER = "SELECTED_LAYER"
+
+# events for the view
+VIEW_POSITION = "VIEW_POSITION"
+SCALE_CHANGED = "SCALE_CHANGED"
+MAP_REPLACED = "MAP_REPLACED"
+
+# event for a dockable window
+DOCKABLE_DOCKED   = "DOCKABLE_DOCKED"
+DOCKABLE_UNDOCKED = "DOCKABLE_UNDOCKED"
+DOCKABLE_CLOSED   = "DOCKABLE_CLOSED"
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/multiplechoicedialog.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/multiplechoicedialog.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/multiplechoicedialog.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,59 @@
+# Copyright (c) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""A dialog for entering multiple choice from a list of strings.
+
+This dialog is actually a class contained by the wxPython Library.
+However, the wxMultipleChoiceDialog did not pass the style in 2.4.0.
+
+As soon as Thuban does not support wxPython 2.4.0 any more,
+this module can be removed and the official wxMultipleChoiceDialog
+of the wxPython Library be used directly."""
+
+__version__ = "$Revision: 2700 $"
+
+import wx
+
+class wxMultipleChoiceDialog(wx.Dialog):
+    """This is a copy of the class wxPython.lib.dialogs.wxMultipleChoiceDialog
+    and fixes the bug that the style now is passed on (this is fixed
+    in version wxPython 2.4.1).
+    """
+    def __init__(self, parent, msg, title, lst, pos = wx.DefaultPosition,
+                 size = (200,200), style = wx.DEFAULT_DIALOG_STYLE):
+        wx.Dialog.__init__(self, parent, -1, title, pos, size, style)
+        x, y = pos
+        if x == -1 and y == -1:
+            self.CenterOnScreen(wx.wxBOTH)
+        dc = wx.wxClientDC(self)
+        height = 0
+        for line in msg.splitlines():
+            height = height + dc.GetTextExtent(msg)[1] + 4
+        stat = wx.wxStaticText(self, -1, msg)
+        self.lbox = wx.wxListBox(self, 100, wx.wxDefaultPosition,
+                                 wx.wxDefaultSize, lst, wx.wxLB_MULTIPLE)
+        ok = wx.wxButton(self, wx.wxID_OK, "OK")
+        cancel = wx.wxButton(self, wx.wxID_CANCEL, "Cancel")
+        stat.SetConstraints(Layoutf('t=t10#1;l=l5#1;r=r5#1;h!%d' % (height,),
+                                   (self,)))
+        self.lbox.SetConstraints(Layoutf('t=b10#2;l=l5#1;r=r5#1;b=t5#3',
+                                 (self, stat, ok)))
+        ok.SetConstraints(Layoutf('b=b5#1;x%w25#1;w!80;h!25', (self,)))
+        cancel.SetConstraints(Layoutf('b=b5#1;x%w75#1;w!80;h!25', (self,)))
+        self.SetAutoLayout(1)
+        self.lst = lst
+        self.Layout()
+
+    def GetValue(self):
+        return self.lbox.GetSelections()
+
+    def GetValueString(self):
+        sel = self.lbox.GetSelections()
+        val = []
+        for i in sel:
+            val.append(self.lst[i])
+        return tuple(val)

Added: packages/thuban/branches/upstream/current/Thuban/UI/projdialog.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/projdialog.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/projdialog.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1050 @@
+# Copyright (c) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+# Frank Koormann <frank.koormann at intevation.de>
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Projection dialog"""
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: projdialog.py 2700 2006-09-18 14:27:02Z dpinte $
+
+import sys, os
+import wx
+
+from Thuban import _
+
+from Thuban.Model.proj import Projection, ProjFile
+
+from Thuban.Model.resource import get_user_proj_file, get_system_proj_file, \
+                                  read_proj_file, write_proj_file, \
+                                  DEFAULT_PROJ_FILE, EPSG_PROJ_FILE, \
+                                  EPSG_DEPRECATED_PROJ_FILE
+from Thuban.UI.dialogs import NonModalNonParentDialog
+
+from common import ThubanBeginBusyCursor, ThubanEndBusyCursor
+from sizers import NotebookLikeSizer
+from projlist import PROJ_SELECTION_CHANGED, ProjectionList
+from common import ThubanBeginBusyCursor, ThubanEndBusyCursor
+
+
+
+ID_PROJ_PROJCHOICE = 4002
+ID_PROJ_ADDTOLIST    = 4003
+ID_PROJ_NEW       = 4004
+ID_PROJ_REVERT    = 4006
+ID_PROJ_AVAIL     = 4009
+ID_PROJ_SAVE      = 4010
+ID_PROJ_IMPORT    = 4011
+ID_PROJ_EXPORT    = 4012
+ID_PROJ_REMOVE    = 4013
+ID_PROJ_PROJNAME  = 4014
+
+CLIENT_PROJ = 0
+CLIENT_PROJFILE = 1
+
+class ProjFrame(NonModalNonParentDialog):
+
+    def __init__(self, parent, name, title, receiver):
+        """Initialize the projection dialog.
+
+        receiver -- An object that implements the following methods:
+                        SetProjection(projection)
+                        GetProjection()
+        """
+        NonModalNonParentDialog.__init__(self, parent, name, title)
+
+        self.projection_panel_defs = [
+            ("tmerc", _("Transverse Mercator"), TMPanel),
+            ("utm", _("Universal Transverse Mercator"), UTMPanel),
+            ("lcc", _("Lambert Conic Conformal"), LCCPanel),
+            ("latlong", _("Geographic"), GeoPanel),
+            ("longlat", _("Geographic"), GeoPanel)]#longlat is an alias of proj
+        self.receiver = receiver
+        self.haveTried = False
+        self.curProjPanel = None
+        self.__usrProjFile = None
+        self._sys_proj_files = {}
+
+        self.build_dialog()
+        self.Layout()
+
+        self.originalProjection = self.receiver.GetProjection()
+
+        self.projection_list.SelectProjection(self.originalProjection)
+        self.projection_list.SetFocus()
+
+    def build_dialog(self):
+        """Build the dialog's widgets and set the event handlers"""
+        self.topBox = top_box = wx.BoxSizer(wx.VERTICAL)
+
+        main_box = wx.BoxSizer(wx.HORIZONTAL)
+        top_box.Add(main_box, 1, wx.ALL|wx.EXPAND)
+
+        #
+        #    The projection list and associated controls
+        #
+        vbox = wx.BoxSizer(wx.VERTICAL)
+        main_box.Add(vbox, 4, wx.ALL|wx.EXPAND)
+
+        #label = wxStaticText(self, -1, _("Available Projections:"))
+        #vbox.Add(label, 0, wxLEFT|wxRIGHT|wxTOP, 4)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        vbox.Add(hbox, 1, wx.ALL|wx.EXPAND)
+        proj_files = [self.load_user_proj(),
+                      self.load_system_proj(DEFAULT_PROJ_FILE)]
+        self.projection_list = ProjectionList(self, proj_files,
+                                              self.receiver.GetProjection())
+        hbox.Add(self.projection_list, 1, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 4)
+        self.projection_list.Subscribe(PROJ_SELECTION_CHANGED,
+                                       self.proj_selection_changed)
+
+        # Projection List specific actions (Import/Export/Remove)
+        buttons = wx.BoxSizer(wx.VERTICAL)
+        hbox.Add(buttons, 0, wx.ALL)
+        self.button_import = wx.Button(self, ID_PROJ_IMPORT, _("Import..."))
+        self.Bind(wx.EVT_BUTTON, self._OnImport, id=ID_PROJ_IMPORT)
+        buttons.Add(self.button_import, 1, wx.ALL|wx.EXPAND, 4)
+        self.button_export = wx.Button(self, ID_PROJ_EXPORT, _("Export..."))
+        self.Bind(wx.EVT_BUTTON, self._OnExport, id=ID_PROJ_EXPORT)
+        buttons.Add(self.button_export, 1, wx.ALL|wx.EXPAND, 4)
+        buttons.Add( (20, 20), 0, wx.EXPAND, 0)
+        self.button_remove = wx.Button(self, ID_PROJ_REMOVE, _("Remove"))
+        self.Bind(wx.EVT_BUTTON, self._OnRemove, id=ID_PROJ_REMOVE)
+        buttons.Add(self.button_remove, 1, wx.ALL|wx.EXPAND, 4)
+
+        buttons.Add( (20, 20), 0, wx.EXPAND, 0)
+        label = wx.StaticText(self, -1, _("Show EPSG:"))
+        buttons.Add(label, 0, wx.LEFT|wx.RIGHT|wx.TOP, 4)
+        self.check_epsg = wx.CheckBox(self, -1, _("Normal"))
+        self.Bind(wx.EVT_CHECKBOX, self._OnShowEPSG, id=self.check_epsg.GetId())
+        buttons.Add(self.check_epsg, 1, wx.ALL|wx.EXPAND, 4)
+        self.check_epsg_depr = wx.CheckBox(self, -1, _("Deprecated"))
+        self.Bind(wx.EVT_CHECKBOX, self._OnShowEPSG, id=self.check_epsg_depr.GetId())
+        buttons.Add(self.check_epsg_depr, 1, wx.ALL|wx.EXPAND, 4)
+
+        # The file path
+        self.projfilepath = wx.StaticText(self, -1, "")
+        vbox.Add(self.projfilepath, 0, wx.ALL|wx.EXPAND)
+
+        #
+        #   The projection editor part
+        #
+        self.edit_box = wx.StaticBox(self, -1, _("Edit"))
+        sizer_edit = wx.StaticBoxSizer(self.edit_box, wx.HORIZONTAL)
+        main_box.Add(sizer_edit, 5, wx.ALL|wx.EXPAND)
+
+        # Projection Specific Entries (Name/Projection)
+        self.sizer_projctrls = wx.BoxSizer(wx.VERTICAL)
+        sizer_edit.Add(self.sizer_projctrls, 1, wx.ALL|wx.EXPAND)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        self.sizer_projctrls.Add(hbox, 0, wx.ALL|wx.EXPAND)
+        label = wx.StaticText(self, -1, _("Name:"))
+        hbox.Add(label, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.projname = wx.TextCtrl(self, ID_PROJ_PROJNAME, "")
+        self.Bind(wx.EVT_TEXT, self._OnProjName, id=ID_PROJ_PROJNAME)
+        hbox.Add(self.projname, 1, wx.ALL|wx.EXPAND, 4)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        self.sizer_projctrls.Add(hbox, 0, wx.ALL|wx.EXPAND)
+        label = wx.StaticText(self, -1, _("Projection:"))
+        hbox.Add(label, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.projchoice = wx.Choice(self, ID_PROJ_PROJCHOICE)
+        self.projchoice.SetSelection(0)
+        self.Bind(wx.EVT_CHOICE, self._OnProjChoice, id=ID_PROJ_PROJCHOICE)
+        hbox.Add(self.projchoice, 1, wx.ALL|wx.EXPAND, 4)
+        # Fill the projection choice list.
+        self.nbsizer = NotebookLikeSizer()
+        self.sizer_projctrls.Add(self.nbsizer, 1,
+                                 wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 3)
+        self.projection_panels = []
+        self.projchoice.Append(_("<Unknown>"), "")
+        for proj_type, name, cls in self.projection_panel_defs:
+            self.projchoice.Append(name, proj_type)
+            panel = cls(self, self.receiver)
+            panel.Hide()
+            panel.projection_index = len(self.projection_panels)
+            panel.projection_type = proj_type
+            self.projection_panels.append(panel)
+            self.nbsizer.Add(panel)
+        self.unknown_projection_panel = UnknownProjPanel(self, self.receiver)
+        self.unknown_projection_panel.Hide()
+        self.nbsizer.Add(self.unknown_projection_panel)
+
+        # Projection Specific actions (New/Save/Add)
+        buttons = wx.BoxSizer(wx.VERTICAL)
+        sizer_edit.Add(buttons, 0, wx.ALL)
+        self.button_new = wx.Button(self, ID_PROJ_NEW, _("New"))
+        self.Bind(wx.EVT_BUTTON, self._OnNew, id=ID_PROJ_NEW)
+        buttons.Add(self.button_new, 0, wx.EXPAND|wx.ALL, 4)
+        self.button_add = wx.Button(self, ID_PROJ_ADDTOLIST, _("Add to List"))
+        self.Bind(wx.EVT_BUTTON, self._OnAddToList, id=ID_PROJ_ADDTOLIST)
+        buttons.Add(self.button_add, 0, wx.EXPAND|wx.ALL, 4)
+        buttons.Add( (20, 20), 0, wx.EXPAND, 0)
+        self.button_save = wx.Button(self, ID_PROJ_SAVE,_("Update"))
+        self.Bind(wx.EVT_BUTTON, self._OnSave, id=ID_PROJ_SAVE)
+        buttons.Add(self.button_save, 0, wx.EXPAND|wx.ALL|wx.ALIGN_BOTTOM, 4)
+
+        #
+        # Main Action buttons (Try/Revert/OK/Close)
+        #
+        buttons = wx.BoxSizer(wx.HORIZONTAL)
+        top_box.Add(buttons, 0, wx.ALL|wx.ALIGN_RIGHT, 10)
+        self.button_try = wx.Button(self, wx.ID_APPLY, _("Try"))
+        self.Bind(wx.EVT_BUTTON, self.OnApply, id=wx.ID_APPLY)
+        buttons.Add(self.button_try, 0, wx.RIGHT, 10)
+        self.button_revert = wx.Button(self, ID_PROJ_REVERT, _("Revert"))
+        self.Bind(wx.EVT_BUTTON, self._OnRevert, id=ID_PROJ_REVERT)
+        buttons.Add(self.button_revert, 0, wx.RIGHT, 10)
+        self.button_ok = wx.Button(self, wx.ID_OK, _("OK"))
+        self.Bind(wx.EVT_BUTTON, self.OnOK, id=wx.ID_OK)
+        self.button_ok.SetDefault()
+        buttons.Add(self.button_ok, 0, wx.RIGHT, 10)
+        self.button_close = wx.Button(self, wx.ID_CANCEL, _("Close"))
+        self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
+        buttons.Add(self.button_close, 0, wx.RIGHT, 10)
+
+
+        #
+        # Automatic Layout
+        #
+        self.SetAutoLayout(1)
+        self.SetSizer(top_box)
+        top_box.Fit(self)
+        top_box.SetSizeHints(self)
+
+    def OnClose(self, event):
+        self.projection_list.Unsubscribe(PROJ_SELECTION_CHANGED,
+                                         self.proj_selection_changed)
+        # Destroy the projection list explicitly so that it properly
+        # unsubscribes everything. It would be cleaner if the projection
+        # could do this by itself but wx doesn't always send destroy
+        # events for non-top-level widgets
+        self.projection_list.Destroy()
+        NonModalNonParentDialog.OnClose(self, event)
+
+    def OnApply(self, event):
+        self.__SetProjection()
+        self.haveTried = True
+
+    def OnOK(self, event):
+        self.__SetProjection()
+        self.Close()
+
+    def OnCancel(self, event):
+        """Cancel just closes the dialog, but we call it cancel so we
+        can overload the functionality of wxDialog.
+        """
+        self.Close()
+
+    def _OnRevert(self, event):
+        if self.haveTried:
+            self.receiver.SetProjection(self.originalProjection)
+            self.haveTried = False
+
+    def _OnNew(self, event):
+
+        self.projection_list.ClearSelection()
+        self.projname.Clear()
+
+        # supply a projection panel if there wasn't one
+        if self.curProjPanel is None:
+            self.projchoice.SetSelection(0)
+            self.__DoOnProjChoice()
+
+        if self.curProjPanel is not None:
+            self.curProjPanel.Clear()
+
+    def _OnSave(self, event):
+
+        sel = self.projection_list.selected_projections()
+        assert len(sel) == 1,  "button shouldn't be enabled"
+
+        proj, projfile = sel[0]
+
+        assert proj is not None and projfile is not None
+
+        newproj = self.__GetProjection()
+
+        if newproj is not None:
+            # FIXME: we should only allow this for the user proj file.
+            projfile.Replace(proj, newproj)
+            self.write_proj_file(projfile)
+            self.projection_list.SelectProjection(newproj)
+
+    def _OnAddToList(self, event):
+
+        proj = self.__GetProjection()
+        if proj is not None:
+            self.__usrProjFile.Add(proj)
+            self.write_proj_file(self.__usrProjFile)
+            self.projection_list.SelectProjection(proj)
+
+    def show_warnings(self, title, filename, warnings):
+        """Show the warnings (a list of strings) in a dialog
+
+        If the list is empty no dialog will be shown.
+        """
+        if warnings:
+            text = (_('Warnings when reading "%s":\n\n%s')
+                    % (filename, "\n\n".join(warnings)))
+            self.parent.RunMessageBox(title, text)
+
+    def _OnImport(self, event):
+        """Handler for the 'Import' button
+
+        Ask the user for a filename, read the projections from that file
+        add them to the user ProjFile object and write the user file
+        back to disk.
+        """
+        dlg = wx.FileDialog(self, _("Import"),
+                self.parent.application.Path("projection"), style = wx.OPEN)
+
+        if dlg.ShowModal() == wx.ID_OK:
+            path = dlg.GetPath()
+
+            ThubanBeginBusyCursor()
+            try:
+                try:
+                    projFile, warnings = read_proj_file(path)
+                except IOError, (errno, errstr):
+                    self.__ShowError(dlg.GetPath(), errstr)
+                else:
+                    self.show_warnings(_("Warnings"), path, warnings)
+                    for proj in projFile.GetProjections():
+                        self.__usrProjFile.Add(proj)
+                    self.write_proj_file(self.__usrProjFile)
+                    self.parent.application.SetPath("projection", path)
+            finally:
+                ThubanEndBusyCursor()
+        dlg.Destroy()
+
+    def _OnExport(self, event):
+        """Handler for the 'Export' button.
+
+        Ask the user for a filename and write the selected projections
+        to that file.
+        """
+        sel = self.projection_list.selected_projections()
+        assert len(sel) != 0, "button should be disabled"
+
+        dlg = wx.FileDialog(self, _("Export"),
+                self.parent.application.Path("projection"),
+                style=wx.SAVE|wx.OVERWRITE_PROMPT)
+
+        if dlg.ShowModal() == wx.ID_OK:
+            proj_file = ProjFile(dlg.GetPath())
+            for proj, pf in sel:
+                if proj is not None:
+                    proj_file.Add(proj)
+            self.write_proj_file(proj_file)
+            self.parent.application.SetPath("projection", dlg.GetPath())
+
+        dlg.Destroy()
+
+    def _OnRemove(self, event):
+        """Handler for the 'Remove' button
+
+        Remove any selected projection that came from the user's
+        ProjFile. If the user ProjFile was modified write it back to
+        disk.
+        """
+        sel = self.projection_list.selected_projections()
+        assert len(sel) != 0, "button should be disabled!"
+
+        modified = False
+        for proj, pf in sel:
+            if proj is not None and pf is self.__usrProjFile:
+                pf.Remove(proj)
+                modified = True
+
+        if modified:
+            self.write_proj_file(self.__usrProjFile)
+
+    def _OnShowEPSG(self, event):
+        """Handler for the EVT_CHECKBOX events from the EPSG check button
+
+        If the button is checked add the EPSG_PROJ_FILE to the list of
+        projfiles shown by the projection list. Otherwise remove it
+        """
+        proj_files = [self.load_user_proj(),
+                      self.load_system_proj(DEFAULT_PROJ_FILE)]
+        if self.check_epsg.IsChecked():
+            proj_files.append(self.load_system_proj(EPSG_PROJ_FILE))
+        if self.check_epsg_depr.IsChecked():
+            proj_files.append(self.load_system_proj(EPSG_DEPRECATED_PROJ_FILE))
+        self.projection_list.SetProjFiles(proj_files)
+
+    def _OnProjName(self, event):
+        self.__VerifyButtons()
+
+    def __ShowError(self, filename, errstr):
+        wx.MessageDialog(self,
+            _("The following error occured:\n") +
+            filename + "\n" + errstr,
+            _("Error"), wx.OK | wx.ICON_ERROR).ShowModal()
+
+    def __VerifyButtons(self):
+        """Update button sensitivity"""
+
+        num_sel = self.projection_list.GetSelectedItemCount()
+
+        self.button_import.Enable(True)
+        self.button_export.Enable(True)
+        self.button_save.Enable(True)
+        self.button_remove.Enable(True)
+
+        self.edit_box.Enable(True)
+
+        for ctrl in [self.button_import,
+                     self.button_export,
+                     self.button_remove,
+                     self.button_save,
+                     self.button_add,
+                     self.projchoice,
+                     self.projname,
+                     self.edit_box]:
+            ctrl.Enable(True)
+
+        if self.curProjPanel is not None:
+            self.curProjPanel.Enable(True)
+
+        if num_sel == 0:
+            self.button_import.Enable(True)
+            self.button_export.Enable(False)
+            self.button_remove.Enable(False)
+            self.button_save.Enable(False)
+
+        elif num_sel == 1:
+
+            selection = self.projection_list.selected_projections()
+            proj, projFile = selection[0]
+
+            self.button_save.Enable(len(self.projname.GetValue()) > 0)
+            self.button_add.Enable(len(self.projname.GetValue()) > 0)
+
+            if proj is None:
+                # <None> is selected
+                for ctrl in [self.button_export,
+                             self.button_remove,
+                             self.button_save,
+                             self.button_add,
+                             self.projchoice,
+                             self.projname]:
+                    ctrl.Enable(False)
+
+                if self.curProjPanel is not None:
+                    self.curProjPanel.Enable(False)
+
+            elif proj is self.originalProjection:
+                self.button_remove.Enable(False)
+
+            if projFile is None:
+                self.button_save.Enable(False)
+
+        else:
+            self.edit_box.Enable(False)
+
+    def proj_selection_changed(self, projs):
+        """Subscribed to the projection_list's PROJ_SELECTION_CHANGED message
+
+        Update the dialog to reflect the new selection.
+        """
+        if len(projs) == 0:
+            self.projfilepath.SetLabel(_("No Projections selected"))
+        elif len(projs) == 1:
+            proj, projfile = projs[0]
+            if proj is None:
+                # user selected <None>
+                self.projname.Clear()
+                self.projfilepath.SetLabel("")
+            else:
+                if projfile is not None:
+                    filename = os.path.basename(projfile.GetFilename())
+                    self.projfilepath.SetLabel(_("Source of Projection: %s")
+                                               % filename)
+                else:
+                    # only None if the currently used projection is selected
+                    self.projfilepath.SetLabel("")
+
+                self.projname.SetValue(proj.Label())
+
+                myProjType = proj.GetParameter("proj")
+                i = 0
+                for projType, name, cls in self.projection_panel_defs:
+                    if myProjType == projType:
+                        self.projchoice.Enable(True)
+                        self.projchoice.SetSelection(i + 1)
+                        self.__DoOnProjChoice()
+
+                        #
+                        # self.curProjPanel should not be null
+                        # after a call to __DoOnProjChoice
+                        #
+                        assert self.curProjPanel is not None
+
+                        self.curProjPanel.SetProjection(proj)
+                        break
+                    i += 1
+                else:
+                    self.projchoice.Select(0)
+                    self.projchoice.Disable()
+                    self._show_proj_panel(UnknownProjPanel)
+                    assert self.curProjPanel is not None
+                    self.curProjPanel.SetProjection(proj)
+        else:
+            self.projfilepath.SetLabel(_("Multiple Projections selected"))
+
+        self.__VerifyButtons()
+
+    def _OnProjChoice(self, event):
+        self.__DoOnProjChoice()
+
+    def __DoOnProjChoice(self):
+        """Create and layout a projection panel based on the selected
+        projection type.
+
+        This is necessary to have in seperate method since calls to
+        wxChoice.SetSelection() do not trigger an event.
+
+        At the end of this method self.curProjPanel will not be None
+        if there was a item selected.
+        """
+        choice = self.projchoice
+
+        sel = choice.GetSelection()
+        if sel != -1:
+            proj_type = choice.GetClientData(sel)
+            for t, name, cls in self.projection_panel_defs:
+                if t == proj_type:
+                    self._show_proj_panel(cls)
+                    break
+        # FIXME: what to do if sel == -1?
+
+    def _show_proj_panel(self, panel_class):
+        """Show the panel as the projection panel"""
+        if panel_class is UnknownProjPanel:
+            self.button_ok.Disable()
+            self.button_try.Disable()
+            self.edit_box.Disable()
+            self.nbsizer.Activate(self.unknown_projection_panel)
+            self.curProjPanel = self.unknown_projection_panel
+        else:
+            self.button_ok.Enable(True)
+            self.button_try.Enable(True)
+            self.edit_box.Enable(True)
+            self.unknown_projection_panel.Hide()
+            for panel in self.projection_panels:
+                if panel.__class__ is panel_class:
+                    self.nbsizer.Activate(panel)
+                    self.curProjPanel = panel
+
+    def __SetProjection(self):
+        """Set the receiver's projection."""
+
+        #
+        # save the original projection only once in case 
+        # we try to apply several different projections
+        #
+        self.receiver.SetProjection(self.__GetProjection())
+
+    def __GetProjection(self):
+        """Return a suitable Projection object based on the current
+        state of the dialog box selections.
+
+        Could be None.
+        """
+
+        assert self.projection_list.GetSelectedItemCount() < 2, \
+               "button should be disabled"
+
+        sel = self.projection_list.selected_projections()
+        if len(sel) == 1:
+            if sel[0][0] is None:
+                # <None> is selected
+                return None
+
+        # self.curProjPanel should always contain the most relevant data
+        # for a projection
+        if self.curProjPanel is not None:
+            parameters = self.curProjPanel.GetParameters()
+            if parameters is not None:
+                return Projection(parameters, self.projname.GetValue())
+
+        return None
+
+    def load_user_proj(self):
+        """Return the user's ProjFile
+
+        If the file has not yet been loaded by the dialog, load it first
+        with get_user_proj_file and cache it in self.__usrProjFile.
+
+        Show a busy cursor while loading the file.
+
+        If the file is not available, leave a note to the console.
+        """
+        if self.__usrProjFile is None:
+            ThubanBeginBusyCursor()
+            try:
+                projfile, warnings = get_user_proj_file()
+                if warnings:
+                    sys.stderr.write("".join(warnings))
+                    sys.stderr.write("\n")
+                self.__usrProjFile = projfile
+            finally:
+                ThubanEndBusyCursor()
+        return self.__usrProjFile
+
+    def load_system_proj(self, name):
+        """Load the system ProjFile with the given name.
+
+        If the file has not been loaded yet, load it first with
+        get_system_proj_file and put it into the cache. The name is
+        simply forwarded to get_system_proj_file.
+
+        Show a busy cursor while loading the file.
+        """
+        if name not in self._sys_proj_files:
+            ThubanBeginBusyCursor()
+            try:
+                projfile, warnings = get_system_proj_file(name)
+                self.show_warnings(_("Warnings"), projfile.GetFilename(),
+                                   warnings)
+                self._sys_proj_files[name] = projfile
+            finally:
+                ThubanEndBusyCursor()
+        return self._sys_proj_files[name]
+
+    def write_proj_file(self, proj_file):
+        """Write the ProjFile object proj_file back to its file
+
+        Show a busy cursor while writing and if an error occurs show a
+        dialog with the error message.
+        """
+        try:
+            ThubanBeginBusyCursor()
+            try:
+                write_proj_file(proj_file)
+            finally:
+                ThubanEndBusyCursor()
+        except IOError, (errno, errstr):
+            self.__ShowError(proj_file.GetFilename(), errstr)
+
+
+
+class ProjPanel(wx.Panel):
+    """Base class for all projection panels."""
+
+    def __init__(self, parent):
+        wx.Panel.__init__(self, parent, -1)
+
+        self.__ellps = wx.Choice(self, -1)
+        self.ellpsData = [("", _("<Unknown>")),
+                          ("airy"  , _("Airy")),
+                          ("bessel", _("Bessel 1841")),
+                          ("clrk66", _("Clarke 1866")),
+                          ("clrk80", _("Clarke 1880")),
+                          ("GRS80" , _("GRS 1980 (IUGG, 1980)")),
+                          ("intl"  , _("International 1909 (Hayford)")),
+                          ("WGS84" , _("WGS 84"))]
+
+        for tag, name in self.ellpsData:
+            self.__ellps.Append(name, tag)
+
+        self.__ellps.SetSelection(0)
+
+    def _DoLayout(self, childPanel = None):
+
+        panelSizer = wx.BoxSizer(wx.VERTICAL)
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        sizer.Add(wx.StaticText(self, -1, _("Ellipsoid:")), 0,
+                                    wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        sizer.Add(self.__ellps, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        panelSizer.Add(sizer, 0, wx.ALL|wx.EXPAND, 4)
+
+        if childPanel is not None:
+            panelSizer.Add(childPanel, 0, wx.EXPAND, 0)
+
+        self.SetAutoLayout(1)
+        self.SetSizer(panelSizer)
+        panelSizer.Fit(self)
+        panelSizer.SetSizeHints(self)
+        self.Layout()
+
+    def SetProjection(self, proj):
+        if proj is not None:
+            param = proj.GetParameter("ellps")
+            i = 0
+            for tag, name in self.ellpsData:
+                if param == tag:
+                    self.__ellps.SetSelection(i)
+                    return # returning early!
+                i += 1
+
+        #
+        # if proj is none, or the parameter couldn't be found...
+        #
+        self.__ellps.SetSelection(0)
+
+    def GetParameters(self):
+        ellps = self.__ellps.GetSelection()
+        if ellps > 0:
+            return ["ellps=" + self.__ellps.GetClientData(ellps)]
+        return []
+
+
+ID_TMPANEL_LAT = 4001
+ID_TMPANEL_LONG = 4002
+ID_TMPANEL_FASLE_EAST = 4003
+ID_TMPANEL_FALSE_NORTH = 4004
+ID_TMPANEL_SCALE = 4005
+
+class UnknownProjPanel(ProjPanel):
+
+    """Panel for unknown projection types"""
+
+    def __init__(self, parent, receiver):
+        ProjPanel.__init__(self, parent)
+
+        self.__text = _("Thuban does not know the parameters\n"
+                        "for the current projection and cannot\n"
+                        "display a configuration panel.\n\n"
+                        "The unidentified set of parameters is:\n\n")
+
+        self.__textbox = wx.TextCtrl(self, -1, self.__text, size=(100,200),
+                            style=wx.TE_READONLY|wx.TE_MULTILINE|wx.TE_LINEWRAP)
+        self._DoLayout()
+
+    def _DoLayout(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        sizer.Add(self.__textbox, 0, wx.ALL|wx.EXPAND, 4)
+
+        ProjPanel._DoLayout(self, sizer)
+
+    def GetProjName(self):
+        return "Unknown"
+
+    def SetProjection(self, proj):
+        """Append the available parameters to the info text."""
+        text = self.__text
+        for param in proj.GetAllParameters():
+            text = text + '%s\n' % param
+        self.__textbox.SetValue(text)
+
+    def GetParameters(self):
+        return None
+
+class TMPanel(ProjPanel):
+    """Projection panel for Transverse Mercator."""
+
+    def __init__(self, parent, receiver):
+        ProjPanel.__init__(self, parent)
+
+        self.__latitude = wx.TextCtrl(self, ID_TMPANEL_LAT)
+        self.__longitude = wx.TextCtrl(self, ID_TMPANEL_LONG)
+        self.__falseEast = wx.TextCtrl(self, ID_TMPANEL_FASLE_EAST)
+        self.__falseNorth = wx.TextCtrl(self, ID_TMPANEL_FALSE_NORTH)
+        self.__scale = wx.TextCtrl(self, ID_TMPANEL_SCALE)
+
+        self._DoLayout()
+
+    def _DoLayout(self):
+
+        sizer = wx.FlexGridSizer(4, 2, 0, 0)
+        sizer.Add(wx.StaticText(self, -1, _("Latitude:")), 0, wx.ALL, 4)
+        sizer.Add(self.__latitude, 0, wx.ALL, 4)
+        sizer.Add(wx.StaticText(self, -1, _("Longitude:")), 0, wx.ALL, 4)
+        sizer.Add(self.__longitude, 0, wx.ALL, 4)
+        sizer.Add(wx.StaticText(self, -1, _("False Easting:")), 0, wx.ALL, 4)
+        sizer.Add(self.__falseEast, 0, wx.ALL, 4)
+        sizer.Add(wx.StaticText(self, -1, _("False Northing:")), 0, wx.ALL, 4)
+        sizer.Add(self.__falseNorth, 0, wx.ALL, 4)
+        sizer.Add(wx.StaticText(self, -1, _("Scale Factor:")), 0, wx.ALL, 4)
+        sizer.Add(self.__scale, 0, wx.ALL, 4)
+
+        ProjPanel._DoLayout(self, sizer)
+
+    def GetProjName(self):
+        return _("Transverse Mercator")
+
+    def SetProjection(self, proj):
+        ProjPanel.SetProjection(self, proj)
+
+        self.__latitude.SetValue(proj.GetParameter("lat_0"))
+        self.__longitude.SetValue(proj.GetParameter("lon_0"))
+        self.__falseEast.SetValue(proj.GetParameter("x_0"))
+        self.__falseNorth.SetValue(proj.GetParameter("y_0"))
+        self.__scale.SetValue(proj.GetParameter("k"))
+
+        ProjPanel.SetProjection(self, proj)
+
+    def GetParameters(self):
+        params = ["proj=tmerc",
+                  "lat_0=" + self.__latitude.GetValue(),
+                  "lon_0=" + self.__longitude.GetValue(),
+                  "x_0="   + self.__falseEast.GetValue(),
+                  "y_0="   + self.__falseNorth.GetValue(),
+                  "k="     + self.__scale.GetValue()]
+        params.extend(ProjPanel.GetParameters(self))
+        return params
+
+    def Clear(self):
+        self.__latitude.Clear()
+        self.__longitude.Clear()
+        self.__falseEast.Clear()
+        self.__falseNorth.Clear()
+        self.__scale.Clear()
+
+        ProjPanel.Clear(self)
+
+ID_UTMPANEL_ZONE = 4001
+ID_UTMPANEL_SOUTH = 4002
+ID_UTMPANEL_PROP = 4003
+
+class UTMPanel(ProjPanel):
+    """Projection Panel for Universal Transverse Mercator."""
+
+    def __init__(self, parent, receiver):
+        ProjPanel.__init__(self, parent)
+
+        self.receiver = receiver
+
+        self.__zone = wx.SpinCtrl(self, ID_UTMPANEL_ZONE, "1", min=1, max=60)
+        self.__propButton = wx.Button(self, ID_UTMPANEL_PROP, _("Propose"))
+        self.__south = wx.CheckBox(self, ID_UTMPANEL_SOUTH,
+                                  _("Southern Hemisphere"))
+
+        self._DoLayout()
+
+        self.Bind(wx.EVT_BUTTON, self._OnPropose, id=ID_UTMPANEL_PROP)
+
+    def _DoLayout(self):
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        psizer = wx.BoxSizer(wx.HORIZONTAL)
+        psizer.Add(wx.StaticText(self, -1, _("Zone:")), 0, wx.ALL, 4)
+        psizer.Add(self.__zone, 0, wx.ALL, 4)
+        psizer.Add(self.__propButton, 0, wx.ALL, 4)
+        sizer.Add(psizer, 0, wx.ALL, 4)
+        sizer.Add(self.__south, 0, wx.ALL, 4)
+
+        ProjPanel._DoLayout(self, sizer)
+
+    def GetProjName(self):
+        return _("Universal Transverse Mercator")
+
+    def SetProjection(self, proj):
+        self.__zone.SetValue(int(proj.GetParameter("zone")))
+        self.__south.SetValue(proj.GetParameter("south") != "")
+        ProjPanel.SetProjection(self, proj)
+
+    def GetParameters(self):
+        params = ["proj=utm", "zone=" + str(self.__zone.GetValue())]
+        if self.__south.IsChecked():
+            params.append("south")
+
+        params.extend(ProjPanel.GetParameters(self))
+        return params
+
+    def Clear(self):
+        self.__zone.SetValue(1)
+        self.__south.SetValue(False)
+        ProjPanel.Clear(self)
+
+    def _OnPropose(self, event):
+        """Call the propose dialog.
+        If the receiver (e.g. the current map) has no bounding box,
+        inform the user accordingly.
+        """
+        bb = self.receiver.BoundingBox()
+        if bb is None:
+            dlg = wx.MessageDialog(self,
+                    _("Can not propose: No bounding box found."),
+                    _("Projection: Propose UTM Zone"),
+                    wx.OK | wx.ICON_INFORMATION)
+            dlg.CenterOnParent()
+            result = dlg.ShowModal()
+            dlg.Destroy()
+            return
+
+        dlg = UTMProposeZoneDialog(self, self.receiver.BoundingBox())
+        if dlg.ShowModal() == wx.ID_OK:
+            self.__zone.SetValue(dlg.GetProposedZone())
+
+class LCCPanel(ProjPanel):
+    """Projection Panel for Lambert Conic Conformal."""
+
+    def __init__(self, parent, receiver):
+        ProjPanel.__init__(self, parent)
+
+        self.__fspLatitude = wx.TextCtrl(self, -1)
+        self.__sspLatitude = wx.TextCtrl(self, -1)
+        self.__meridian    = wx.TextCtrl(self, -1)
+        self.__originLat   = wx.TextCtrl(self, -1)
+        self.__falseEast   = wx.TextCtrl(self, -1)
+        self.__falseNorth  = wx.TextCtrl(self, -1)
+
+        self._DoLayout()
+
+    def _DoLayout(self):
+
+        sizer = wx.FlexGridSizer(6, 2, 0, 0)
+        sizer.Add(wx.StaticText(self, -1,
+            _("Latitude of first standard parallel:")))
+        sizer.Add(self.__fspLatitude, 0, wx.ALL, 4)
+        sizer.Add(wx.StaticText(self, -1,
+            _("Latitude of second standard parallel:")))
+        sizer.Add(self.__sspLatitude, 0, wx.ALL, 4)
+        sizer.Add(wx.StaticText(self, -1, _("Central Meridian:")))
+        sizer.Add(self.__meridian, 0, wx.ALL, 4)
+        sizer.Add(wx.StaticText(self, -1, _("Latitude of origin:")))
+        sizer.Add(self.__originLat, 0, wx.ALL, 4)
+        sizer.Add(wx.StaticText(self, -1, _("False Easting:")))
+        sizer.Add(self.__falseEast, 0, wx.ALL, 4)
+        sizer.Add(wx.StaticText(self, -1, _("False Northing:")))
+        sizer.Add(self.__falseNorth, 0, wx.ALL, 4)
+
+        ProjPanel._DoLayout(self, sizer)
+
+    def GetProjName(self):
+        return _("Lambert Conic Conformal")
+
+    def SetProjection(self, proj):
+        self.__fspLatitude.SetValue(proj.GetParameter("lat_1"))
+        self.__sspLatitude.SetValue(proj.GetParameter("lat_2"))
+        self.__originLat.SetValue(proj.GetParameter("lat_0"))
+        self.__meridian.SetValue(proj.GetParameter("lon_0"))
+        self.__falseEast.SetValue(proj.GetParameter("x_0"))
+        self.__falseNorth.SetValue(proj.GetParameter("y_0"))
+
+        ProjPanel.SetProjection(self, proj)
+
+    def GetParameters(self):
+        params = ["proj=lcc",
+                  "lat_1=" + self.__fspLatitude.GetValue(),
+                  "lat_2=" + self.__sspLatitude.GetValue(),
+                  "lat_0=" + self.__originLat.GetValue(),
+                  "lon_0=" + self.__meridian.GetValue(),
+                  "x_0=" + self.__falseEast.GetValue(),
+                  "y_0=" + self.__falseNorth.GetValue()]
+
+        params.extend(ProjPanel.GetParameters(self))
+        return params
+
+    def Clear(self):
+        self.__fspLatitude.Clear()
+        self.__sspLatitude.Clear()
+        self.__originLat.Clear()
+        self.__meridian.Clear()
+        self.__falseEast.Clear()
+        self.__falseNorth.Clear()
+
+        ProjPanel.Clear(self)
+
+class GeoPanel(ProjPanel):
+    """Projection Panel for a Geographic Projection."""
+
+    def __init__(self, parent, receiver):
+        ProjPanel.__init__(self, parent)
+
+        self.__choices = [(_("Degrees"), "0.017453"),
+                          (_("Radians"), "1")]
+
+        self.__scale = wx.Choice(self, -1)
+        for choice, value in self.__choices:
+            self.__scale.Append(choice, value)
+
+        self._DoLayout()
+
+    def GetProjName(self):
+        return _("Geographic")
+
+    def SetProjection(self, proj):
+        value = proj.GetParameter("to_meter")
+        for i in range(len(self.__choices)):
+            choice, data = self.__choices[i]
+            if value == data:
+                self.__scale.SetSelection(i)
+        ProjPanel.SetProjection(self, proj)
+
+    def GetParameters(self):
+        params = ["proj=latlong",
+                  "to_meter=%s" % self.__scale.GetClientData(
+                                  self.__scale.GetSelection())]
+
+        params.extend(ProjPanel.GetParameters(self))
+        return params
+
+    def Clear(self):
+        ProjPanel.Clear(self)
+
+    def _DoLayout(self):
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+        sizer.Add(wx.StaticText(self, -1, _("Source Data is in: ")),
+                  0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        sizer.Add(self.__scale, 1, wx.EXPAND|wx.ALL, 4)
+
+        self.__scale.SetSelection(0)
+
+        ProjPanel._DoLayout(self, sizer)
+
+
+ID_UTM_PROPOSE_ZONE_DIALOG_TAKE   = 4001
+ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL = 4002
+class UTMProposeZoneDialog(wx.Dialog):
+
+    """Propose a sensible Zone considering the current map extent."""
+
+    def __init__(self, parent, (x, y, x2, y2)):
+        wx.Dialog.__init__(self, parent, -1, _("Projection: Propose UTM Zone"),
+                          wx.DefaultPosition, wx.Size(200, 100))
+        self.parent = parent
+        x = x + 180
+        x2 = x2 + 180
+        center = (x2 - x) / 2 + x
+        self.proposedZone = int(center / 6 + 1)
+        self.dialogLayout()
+
+    def dialogLayout(self):
+        topBox = wx.BoxSizer(wx.VERTICAL)
+
+        textBox = wx.BoxSizer(wx.VERTICAL)
+        textBox.Add(wx.StaticText(self, -1, _("The current map extent center "
+                                             "lies in UTM Zone")),
+                    0, wx.ALIGN_CENTER|wx.ALL, 4)
+        textBox.Add(wx.StaticText(self, -1, str(self.proposedZone)),
+                    0, wx.ALIGN_CENTER|wx.ALL, 4)
+
+        topBox.Add(textBox, 1, wx.EXPAND|wx.ALL, 4)
+
+        buttonBox = wx.BoxSizer(wx.HORIZONTAL)
+        buttonBox.Add(wx.Button(self, ID_UTM_PROPOSE_ZONE_DIALOG_TAKE,
+                      _("Take")), 0, wx.ALL, 4)
+        buttonBox.Add(wx.Button(self, ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL,
+                               _("Cancel")), 0, wx.ALL, 4)
+        topBox.Add(buttonBox, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 10)
+        self.Bind(wx.EVT_BUTTON, self.OnTake, id=ID_UTM_PROPOSE_ZONE_DIALOG_TAKE)
+        self.Bind(wx.EVT_BUTTON, self.OnCancel, id=ID_UTM_PROPOSE_ZONE_DIALOG_CANCEL)
+
+        self.SetAutoLayout(True)
+        self.SetSizer(topBox)
+        topBox.Fit(self)
+        topBox.SetSizeHints(self)
+
+    def OnTake(self, event):
+        self.EndModal(wx.ID_OK)
+
+    def OnCancel(self, event):
+        self.EndModal(wx.ID_CANCEL)
+
+    def GetProposedZone(self):
+        return self.proposedZone

Added: packages/thuban/branches/upstream/current/Thuban/UI/projlist.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/projlist.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/projlist.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,241 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""List control for projections"""
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: projlist.py 2700 2006-09-18 14:27:02Z dpinte $
+
+import wx
+
+from Thuban import _
+
+from Thuban.Lib.connector import Publisher
+
+from Thuban.Model.messages import PROJECTION_ADDED, PROJECTION_REMOVED, \
+     PROJECTION_REPLACED
+
+
+PROJ_SELECTION_CHANGED = "PROJ_SELECTION_CHANGED"
+
+
+class ProjectionList(wx.ListCtrl, Publisher):
+
+    """A ListCtrl that shows a list of projections
+
+    The list control is effectively a view on several ProjFile instances
+    and a specific 'original' projection (e.g. the projection of the
+    current map). The list control subscribes to the change messages of
+    the ProjFile instances to update the list whenever they change.
+
+    When the selection changes the instance sends a
+    PROJ_SELECTION_CHANGED message.
+    """
+
+    def __init__(self, parent, proj_files, orig_proj, ID = -1):
+        """Initialize the ProjectionList
+
+        Parameters:
+
+        parent -- The parent widget
+        proj_files -- a sequence of ProjFile objects
+        orig_proj -- The projection originally selected in the map/layer
+        """
+        wx.ListCtrl.__init__(self, parent, ID, style=wx.LC_REPORT|wx.LC_VIRTUAL)
+
+        self.InsertColumn(0, _("Available Projections"))
+        self.proj_files = proj_files
+        self._subscribe_proj_files()
+        self.orig_proj = orig_proj
+        self.projections = []
+        self.proj_map = {}
+        self.needs_update = False
+        self.update_projections()
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.Bind(wx.EVT_LEFT_UP, self.mouse_left_up)
+        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.item_selected, id=self.GetId())
+        self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.item_deselected, id=self.GetId())
+        self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+    def __del__(self):
+        wx.ListCtrl.__del__()
+        Publisher.__del__()
+
+    def _subscribe_proj_files(self):
+        """Subscribe to the messages of self.proj_files"""
+        for pf in self.proj_files:
+            pf.Subscribe(PROJECTION_ADDED, self.pf_projection_added)
+            pf.Subscribe(PROJECTION_REMOVED, self.pf_projection_removed)
+            pf.Subscribe(PROJECTION_REPLACED, self.pf_projection_replaced)
+
+    def _unsubscribe_proj_files(self):
+        """Unsubscribe from the messages subscribed to in _subscribe_proj_files
+        """
+        for pf in self.proj_files:
+            pf.Unsubscribe(PROJECTION_ADDED, self.pf_projection_added)
+            pf.Unsubscribe(PROJECTION_REMOVED, self.pf_projection_removed)
+            pf.Unsubscribe(PROJECTION_REPLACED, self.pf_projection_replaced)
+
+    def Destroy(self):
+        self._unsubscribe_proj_files()
+        # Call wxListCtrl's method last because afterwards self is not
+        # an instance of ProjectionList anymore as wxPython replaces
+        # self.__class__ with its dead object class
+        Publisher.Destroy(self)
+        wx.ListCtrl.Destroy(self)
+
+    def update_on_idle(self):
+        self.needs_update = True
+
+    def OnIdle(self, evt):
+        if self.needs_update:
+            self.needs_update = False
+            self.update_projections()
+        evt.Skip()
+
+    def update_projections(self):
+        """Update the internal list of projection information"""
+
+        # Remember which projections are selected so that we can select
+        # them again after the update
+        selection = {}
+        for p in self.selected_projections():
+            selection[id(p[0])] = 1
+        old_length = len(self.projections)
+
+        # Build the new projection list
+        projections = [(_("<None>"), None, None)]
+        for pf in self.proj_files:
+            for p in pf.GetProjections():
+                projections.append((p.Label(), p, pf))
+        if self.orig_proj is not None:
+            projections.append((_("%s (current)") % self.orig_proj.Label(),
+                                self.orig_proj, None))
+        self.projections = projections
+        self.projections.sort()
+
+        # Deselect all items with indices higher than the new length
+        # before settign the new item count This is a work-around for a
+        # bug in the listctrl which doesn't updat the selection count
+        # correctly in a call to SetItemCount if items have been
+        # selected with indices higher than the new count.
+        if len(self.projections) < old_length:
+            for i in xrange(len(self.projections), old_length):
+                self.SetItemState(i, 0, wx.LIST_STATE_SELECTED)
+
+        self.SetItemCount(len(self.projections))
+
+        # Reselect the projections that had been selected before.
+        get = selection.get
+        count = 0
+        for i in xrange(len(self.projections)):
+            p = self.projections[i][1]
+            if get(id(p)):
+                state = wx.LIST_STATE_SELECTED
+                count += 1
+            else:
+                state = 0
+            self.SetItemState(i, state, wx.LIST_STATE_SELECTED)
+
+        # If the selection changed send a PROJ_SELECTION_CHANGED message
+        if count != len(selection):
+            self._issue_proj_selection_changed()
+
+    def pf_projection_added(self, proj):
+        """Subscribed to the projfile's PROJECTION_ADDED messages
+
+        Request an update the projection list in idle time.
+        """
+        self.update_on_idle()
+
+    def pf_projection_removed(self, proj):
+        """Subscribed to the projfile's PROJECTION_REMOVED messages
+
+        Request an update the projection list in idle time.
+        """
+        self.update_on_idle()
+
+    def pf_projection_replaced(self, old, new):
+        """Subscribed to the projfile's PROJECTION_REPLACED messages
+
+        Request an update the projection list in idle time.
+        """
+        self.update_on_idle()
+
+    def OnSize(self, evt):
+        self.SetColumnWidth(0, evt.GetSize().width)
+        evt.Skip()
+
+    def SelectProjection(self, proj):
+        """Select the projection and deselect all others."""
+        # Set both the wxLIST_STATE_SELECTED and wxLIST_STATE_FOCUSED
+        # flags on the newly selected item. If only
+        # wxLIST_STATE_SELECTED is set, some other item is focused and
+        # the first time the focus is moved with the keyboard the
+        # selection moves in unexpected ways.
+        state = wx.LIST_STATE_SELECTED|wx.LIST_STATE_FOCUSED
+        for i in range(len(self.projections)):
+            p = self.projections[i][1]
+            self.SetItemState(i, p is proj and state or 0, state)
+
+    def ClearSelection(self):
+        """Deselect all projections."""
+        for i in range(len(self.projections)):
+            self.SetItemState(i, 0, wx.LIST_STATE_SELECTED)
+
+    def SetProjFiles(self, proj_files):
+        """Set the projfile objects whose projections are shown in the list"""
+        self._unsubscribe_proj_files()
+        self.proj_files = proj_files
+        self._subscribe_proj_files()
+        self.update_projections()
+
+    def OnGetItemText(self, item, col):
+        """Callback for the virtual ListCtrl mode"""
+        return self.projections[item][0]
+
+    def OnGetItemAttr(self, item):
+        """Callback for the virtual ListCtrl mode"""
+        return None
+
+    def OnGetItemImage(self, item):
+        """Callback for the virtual ListCtrl mode"""
+        return -1
+
+    def selected_projections(self):
+        """Return a list with all selected projection infos
+
+        The return value is a list of (proj, proj_file) pairs. proj_file
+        is the projection file object the projection was read from, if
+        any. Both proj and proj_file may be None, but if proj_file is
+        not None proj will also not be None.
+        """
+        return [self.projections[i][1:]
+                    for i in range(len(self.projections))
+                        if self.GetItemState(i, wx.LIST_STATE_SELECTED)]
+
+    def _issue_proj_selection_changed(self):
+        """Internal: Issue a PROJ_SELECTION_CHANGED message"""
+        self.issue(PROJ_SELECTION_CHANGED, self.selected_projections())
+
+    def item_selected(self, evt):
+        """Handler for EVT_LIST_ITEM_SELECTED"""
+        self._issue_proj_selection_changed()
+
+    def item_deselected(self, evt):
+        #"""Handler for EVT_LIST_ITEM_DESELECTED"""
+        self._issue_proj_selection_changed()
+
+    def mouse_left_up(self, evt):
+        """Handle EVT_LEFT_UP events. Issue a selection message.
+
+        It's not clear whether the selection really has changed but the
+        selection events send by the list ctrl don't cover selecting
+        ranges of items :(.
+        """
+        self._issue_proj_selection_changed()

Added: packages/thuban/branches/upstream/current/Thuban/UI/rasterlayerproperties.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/rasterlayerproperties.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/rasterlayerproperties.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,138 @@
+# Copyright (c) 2005 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de> 
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Raster Layer Properties dialog"""
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: rasterlayerproperties.py 2700 2006-09-18 14:27:02Z dpinte $
+
+import wx
+
+from Thuban import _
+from Thuban.UI.layerproperties import LayerProperties
+from Thuban.Model.resource import has_gdal_support, gdal_support_status
+
+from Thuban.version import versions
+
+ID_RB_MASK = 4002
+
+class RasterLayerProperties(LayerProperties):
+
+    def __init__(self, parent, name, layer, *args, **kw):
+        LayerProperties.__init__(self, parent, name, layer)
+
+        self.old_state = {}
+        self.old_state["mask_type"] = layer.MaskType()
+
+        LayerProperties.dialog_layout(self)
+
+    def dialog_layout(self, panel, panelBox):
+
+        info = self.layer.ImageInfo()
+
+        if info is None:
+            panelBox.Add(
+                wx.StaticText(panel, -1,
+                _("GDAL image information unavailable. See About box for details.")),
+                0, wx.ALIGN_LEFT | wx.ALL, 4)
+            return
+
+
+        # Bounding Box
+        bbox = self.layer.LatLongBoundingBox()
+        if bbox is None:
+            text = _("Extent (lat-lon): None")
+        else:
+            text = _("Extent (lat-lon): (%g, %g, %g, %g)") % tuple(bbox)
+
+        panelBox.Add(wx.StaticText(panel, -1, text), 0, wx.ALIGN_LEFT|wx.ALL, 4)
+
+        rasterBox = wx.StaticBoxSizer(wx.StaticBox(panel, -1,
+                    _("Image Properties")), wx.VERTICAL)
+
+
+        rasterBox.Add(
+            wx.StaticText(panel, -1,
+            _("Source: %s") % self.layer.GetImageFilename()),
+            0, wx.ALIGN_LEFT | wx.ALL, 4)
+
+        infoBox = wx.BoxSizer(wx.HORIZONTAL)
+
+        nBands = info["nBands"]
+
+        self.usePalIndex = nBands == 1
+
+        infoBox.Add(
+            wx.StaticText(panel, -1, _("Driver: %s") % info["Driver"]),
+            0, wx.ALIGN_LEFT | wx.RIGHT, 10)
+        infoBox.Add(
+            wx.StaticText(panel, -1, _("Size: %ix%i") % info["Size"]),
+            0, wx.ALIGN_LEFT | wx.RIGHT, 10)
+        infoBox.Add(
+            wx.StaticText(panel, -1, _("Number of Bands: %i") % nBands),
+            0, wx.ALIGN_LEFT | wx.RIGHT, 0)
+
+        rasterBox.Add(infoBox, 0, wx.ALIGN_LEFT|wx.ALL, 4)
+
+        # Mask 
+
+        maskBox = wx.BoxSizer(wx.HORIZONTAL)
+
+        if versions['wxPython-tuple'] < (2,5,3):
+            choices = ["None", "Bitmap",
+                       "Alpha (Not support by wxPython %s)" % \
+                       versions['wxPython']]
+        else:
+            choices = ["None", "Bitmap", "Alpha"]
+
+        self.maskRadioBox = wx.RadioBox(panel, ID_RB_MASK, _("Mask Type"),
+                            choices=choices)
+        #self.maskCB = wxCheckBox(panel, -1, _("Use Mask"))
+        maskBox.Add(self.maskRadioBox, 0, wx.RIGHT, 10)
+
+        self.opBox = wx.BoxSizer(wx.HORIZONTAL)
+        self.opSpinLabel = wx.StaticText(panel, -1, _("Opacity:"))
+        self.opBox.Add(self.opSpinLabel, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 4)
+        self.opSpin = wx.SpinCtrl(panel, -1,
+                                 str(self.layer.Opacity()*255),
+                                 initial = self.layer.Opacity()*255,
+                                 min=0, max=255)
+        self.opBox.Add(self.opSpin, 0, wx.ALL, 4)
+        maskBox.Add(self.opBox, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+
+        rasterBox.Add(maskBox, 0, wx.ALL, 4)
+        #rasterBox.Add(opBox, 0, wxALL, 4)
+
+        panelBox.Add(rasterBox, 1, wx.GROW | wx.ALL, 4)
+
+        self.maskRadioBox.SetSelection(self.old_state["mask_type"])
+
+        self.OnMaskSelect(None)
+
+        self.Bind(wx.EVT_RADIOBOX, self.OnMaskSelect, id=ID_RB_MASK)
+
+    def OnTry(self, event):
+        self.set_state()
+
+    def OnOK(self, event):
+        if self.set_state():
+            self.Close()
+
+    def OnRevert(self, event):
+        self.maskRadioBox.SetSelection(self.old_state["mask_type"])
+        self.set_state()
+
+    def OnMaskSelect(self, event):
+        allowOpacity = self.maskRadioBox.GetSelection()==2
+        self.opSpin.Enable(allowOpacity)
+        self.opSpinLabel.Enable(allowOpacity)
+
+    def set_state(self):
+        self.layer.SetMaskType(self.maskRadioBox.GetSelection())
+        self.layer.SetOpacity(self.opSpin.GetValue()/255.0)
+        return True

Added: packages/thuban/branches/upstream/current/Thuban/UI/renderer.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/renderer.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/renderer.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,488 @@
+# Copyright (c) 2001-2006 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de> (2001-2003)
+# Jonathan Coles <jonathan at intevation.de> (2003)
+# Frank Koormann <frank.koormann at intevation.de> (2003)
+# Jan-Oliver Wagner <jan at intevation.de> (2003-2005)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+from __future__ import generators
+
+__version__ = "$Revision: 2712 $"
+# $Source$
+# $Id: renderer.py 2712 2006-10-15 23:27:05Z bernhard $
+
+import cStringIO
+
+import array
+
+import traceback
+
+from Thuban import _
+
+import wx
+
+from wxproj import draw_polygon_shape, draw_polygon_init
+
+from Thuban.UI.common import Color2wxColour
+from Thuban.UI.classifier import ClassDataPreviewer
+from Thuban.UI.scalebar import ScaleBar
+
+from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
+     SHAPETYPE_POINT, RAW_SHAPEFILE
+
+from Thuban.Model.color import Transparent
+import Thuban.Model.resource
+
+from baserenderer import BaseRenderer
+
+from math import floor
+
+from types import StringType
+
+from Thuban.version import versions
+
+if Thuban.Model.resource.has_gdal_support():
+    from gdalwarp import ProjectRasterFile
+
+verbose = 0 # whether to talk more on stdout
+
+# Map the strings used for the format parameter of the draw_raster_data
+# method to the appropriate wxWindows constants
+raster_format_map = {
+    "BMP": wx.BITMAP_TYPE_BMP,
+    "JPEG": wx.BITMAP_TYPE_JPEG,
+    "PNG": wx.BITMAP_TYPE_PNG,
+    "TIFF": wx.BITMAP_TYPE_TIF,
+    "GIF": wx.BITMAP_TYPE_GIF,
+    }
+
+class MapRenderer(BaseRenderer):
+
+    """Class to render a map onto a wxDC"""
+
+    TRANSPARENT_PEN = wx.TRANSPARENT_PEN
+    TRANSPARENT_BRUSH = wx.TRANSPARENT_BRUSH
+
+    def make_point(self, x, y):
+        return wx.Point(int(round(x)), int(round(y)))
+
+    def tools_for_property(self, prop):
+        fill = prop.GetFill()
+        if fill is Transparent:
+            brush = self.TRANSPARENT_BRUSH
+        else:
+            brush = wx.Brush(Color2wxColour(fill), wx.SOLID)
+
+        stroke = prop.GetLineColor()
+        if stroke is Transparent:
+            pen = self.TRANSPARENT_PEN
+        else:
+            pen = wx.Pen(Color2wxColour(stroke), prop.GetLineWidth(), wx.SOLID)
+        return pen, brush
+
+    def low_level_renderer(self, layer):
+        """Override inherited method to provide more efficient renderers
+
+        If the underlying data format is not a shapefile or the layer
+        contains points shapes, simply use what the inherited method
+        returns.
+
+        Otherwise, i.e. for arc and polygon use the more efficient
+        wxproj.draw_polygon_shape and its corresponding parameter
+        created with wxproj.draw_polygon_init.
+        """
+        if (layer.ShapeStore().RawShapeFormat() == RAW_SHAPEFILE
+            and layer.ShapeType() in (SHAPETYPE_ARC, SHAPETYPE_POLYGON)):
+            offx, offy = self.offset
+            x = lambda a, b, c, d: None
+            #return (True, x, None)
+            return (True, draw_polygon_shape,
+                    draw_polygon_init(layer.ShapeStore().Shapefile(),
+                                      self.dc, self.map.projection,
+                                      layer.projection,
+                                      self.scale, -self.scale, offx, offy))
+        else:
+            return BaseRenderer.low_level_renderer(self, layer)
+
+    def label_font(self):
+        return wx.Font(int(round(self.resolution * 10)), wx.SWISS, wx.NORMAL,
+                      wx.NORMAL)
+
+    def projected_raster_layer(self, layer, srcProj, dstProj, extents,
+                               resolution, dimensions, options):
+        """Returns a raster layer image in projected space
+
+        Based on a given filename.  This method must be implemented in
+        classes derived from BaseRenderer.
+        """
+
+        ret = None
+
+        if Thuban.Model.resource.has_gdal_support():
+
+            if versions['wxPython-tuple'] < (2,5,3):
+                options = options | 4  # INVERT_MASK_BITS
+                options = options & ~2 # ALPHA_MASK not supported
+
+            try:
+                if verbose > 0:
+                    print "doing ProjectRasterFile '%s' -> '%s'" % \
+                                (srcProj, dstProj)
+                    print "extents:", extents, "resolution:", resolution
+                    print "dimensions:", dimensions, "options:", options
+                ret = ProjectRasterFile(layer.GetImageFilename(),
+                                        srcProj, dstProj,
+                                        extents, resolution, dimensions,
+                                        options)
+            except (MemoryError, IOError, AttributeError, ValueError):
+                # Why does this catch AttributeError and ValueError?
+                # FIXME: The exception should be communicated to the user
+                # better.
+                traceback.print_exc()
+
+        return ret
+
+    def draw_raster_data(self, x,y, data, format = 'BMP', opacity=1.0):
+
+        mask = None
+        alpha = None
+        width = data[0]
+        height = data[1]
+        image_data, mask_data, alpha_data = data[2]
+
+        if versions['wxPython-tuple'] < (2,5,3):
+            alpha_data = None
+
+        if format == 'RAW':
+            image = wx.EmptyImage(width, height)
+            image.SetData(image_data)
+            if mask_data is not None:
+                mask = wx.BitmapFromBits(mask_data, width, height, 1)
+                mask = wx.Mask(mask)
+            elif alpha_data is not None:
+                # alpha_data is already in the right format
+                alpha = alpha_data
+
+        else:
+            stream = cStringIO.StringIO(image_data)
+            image = wx.ImageFromStream(stream, raster_format_map[format])
+
+            if mask_data is not None:
+                stream = cStringIO.StringIO(mask_data)
+                mask = wx.ImageFromStream(stream, raster_format_map[format])
+                mask = wx.Mask(wx.BitmapFromImage(mask, 1))
+            elif alpha_data is not None:
+                stream = cStringIO.StringIO(alpha_data)
+                alpha = wx.ImageFromStream(stream, raster_format_map[format])
+                alpha = alpha.GetData() #[:] # XXX: do we need to copy this?
+            elif image.HasAlpha():
+                alpha = image.GetAlphaData()
+
+        #
+        # scale down the alpha values the opacity level using a string 
+        # translation table for efficiency.
+        #
+        if alpha is not None:
+            if opacity == 0:
+                return
+            elif opacity == 1:
+                a = alpha
+            else:
+                tr = [int(i*opacity) for i in range(256)]
+                table = array.array('B', tr).tostring()
+                a = alpha.translate(table)
+
+            image.SetAlphaData(a)
+
+        bitmap = wx.BitmapFromImage(image)
+
+        if mask is not None:
+            bitmap.SetMask(mask)
+
+        self.dc.DrawBitmap(bitmap, int(round(x)), int(round(y)), True)
+
+
+class ScreenRenderer(MapRenderer):
+
+    # On the screen we want to see only visible layers by default
+    honor_visibility = 1
+
+    def RenderMap(self, selected_layer, selected_shapes):
+        """Render the map.
+
+        Only the given region (a tuple in window coordinates as returned
+        by a wxrect's asTuple method) needs to be redrawn. Highlight the
+        shapes given by the ids in selected_shapes in the
+        selected_layer.
+        """
+        self.selected_layer = selected_layer
+        self.selected_shapes = selected_shapes
+        self.render_map()
+
+    def RenderMapIncrementally(self):
+        """Render the map.
+
+        Only the given region (a tuple in window coordinates as returned
+        by a wxrect's asTuple method) needs to be redrawn. Highlight the
+        shapes given by the ids in selected_shapes in the
+        selected_layer.
+        """
+        return self.render_map_incrementally()
+
+    def draw_selection_incrementally(self, layer, selected_shapes):
+        """Draw the selected shapes in a emphasized way (i.e.
+        with a special pen and brush.
+        The drawing is performed incrementally, that means every
+        n shapes, the user can have interactions with the map.
+        n is currently fixed to 500.
+
+        layer -- the layer where the shapes belong to.
+        selected_shapes -- a list of the shape-ids representing the
+                           selected shapes for the given layer.
+        """
+        pen = wx.Pen(wx.BLACK, 3, wx.SOLID)
+        brush = wx.Brush(wx.BLACK, wx.CROSS_HATCH)
+
+        shapetype = layer.ShapeType()
+        useraw, func, param = self.low_level_renderer(layer)
+        args = (pen, brush)
+
+        # for point shapes we need to find out the properties
+        # to determine the size. Based on table and field,
+        # we can find out the properties for object - see below.
+        if shapetype == SHAPETYPE_POINT:
+            lc = layer.GetClassification()
+            field = layer.GetClassificationColumn()
+            table = layer.ShapeStore().Table()
+
+        count = 0
+        for index in selected_shapes:
+            count += 1
+            shape = layer.Shape(index)
+
+            # Get the size of the specific property for this
+            # point
+            if shapetype == SHAPETYPE_POINT:
+                if field is not None:
+                    value = table.ReadValue(shape.ShapeID(), field)
+                    group = lc.FindGroup(value)
+                    size = group.GetProperties().GetSize()
+                else:
+                    size = lc.GetDefaultGroup().GetProperties().GetSize()
+                args = (pen, brush, size)
+
+            if useraw:
+                data = shape.RawData()
+            else:
+                data = shape.Points()
+            func(param, data, *args)
+            if count % 500 == 0:
+                yield True
+
+    def layer_shapes(self, layer):
+        """Return the shapeids covered by the region that has to be redrawn
+
+        Call the layer's ShapesInRegion method to determine the ids so
+        that it can use the quadtree.
+        """
+        # FIXME: the quad-tree should be built from the projected
+        # coordinates not the lat-long ones because it's not trivial to
+        # determine an appropriate rectangle in lat-long for a given
+        # rectangle in projected coordinates which we have to start from
+        # here.
+        proj = self.map.projection
+        if proj is not None:
+            inverse = proj.Inverse
+        else:
+            inverse = None
+
+        scale = self.scale
+        offx, offy = self.offset
+        xs = []
+        ys = []
+        x, y, width, height = self.region
+        for winx, winy in ((x, y), (x + width, y),
+                           (x + width, y + height), (x, y + height)):
+            px = (winx - offx) / scale
+            py = -(winy - offy) / scale
+            if inverse:
+                px, py = inverse(px, py)
+            xs.append(px)
+            ys.append(py)
+        left = min(xs)
+        right = max(xs)
+        top = max(ys)
+        bottom = min(ys)
+
+        return layer.ShapesInRegion((left, bottom, right, top))
+
+
+class ExportRenderer(ScreenRenderer):
+
+    honor_visibility = 1
+
+    def __init__(self, *args, **kw):
+        """Initialize the ExportRenderer.
+
+        In addition to all parameters of the the ScreenRender
+        constructor, this class requires and additional keyword argument
+        destination_region with a tuple (minx, miny, maxx, maxy) giving
+        the region in dc coordinates which is to contain the map.
+        """
+        self.destination_region = kw["destination_region"]
+        del kw["destination_region"]
+        ScreenRenderer.__init__(self, *args, **kw)
+
+    def RenderMap(self, selected_layer, selected_shapes):
+        """Render the map.
+
+        The rendering device has been specified during initialisation.
+        The device border distance was set in
+        Thuban.UI.viewport.output_transform().
+
+        RenderMap renders a frame set (one page frame, one around
+        legend/scalebar and one around the map), the map, the legend and
+        the scalebar on the given DC. The map is rendered with the
+        region displayed in the canvas view, centered on the area
+        available for map display.
+        """
+
+        self.selected_layer = selected_layer
+        self.selected_shapes = selected_shapes
+
+        # Get some dimensions
+        llx, lly, urx, ury = self.region
+        mminx, mminy, mmaxx, mmaxy = self.destination_region
+
+        # Manipulate the offset to position the map
+        offx, offy = self.offset
+        # 1. Shift to corner of map drawing area
+        offx = offx + mminx
+        offy = offy + mminy
+
+        # 2. Center the map on the map drawing area:
+        # region identifies the region on the canvas view:
+        # center of map drawing area - half the size of region: rendering origin
+        self.shiftx = (mmaxx - mminx)*0.5 - (urx - llx)*0.5
+        self.shifty = (mmaxy - mminy)*0.5 - (ury - lly)*0.5
+
+        self.offset = (offx+self.shiftx, offy+self.shifty)
+        self.region = (llx + self.shiftx, lly + self.shifty, urx, ury)
+
+        # Draw the map
+        self.dc.BeginDrawing()
+        self.dc.DestroyClippingRegion()
+        self.dc.SetClippingRegion(mminx+self.shiftx, mminy+self.shifty,
+                                  urx, ury)
+        self.render_map()
+        self.dc.EndDrawing()
+
+        # Draw the rest (frames, legend, scalebar)
+        self.dc.BeginDrawing()
+        self.dc.DestroyClippingRegion()
+
+        # Force the font for Legend drawing
+        font = wx.Font(self.resolution * 10, wx.SWISS, wx.NORMAL, wx.NORMAL)
+        self.dc.SetFont(font)
+
+        self.render_frame()
+        self.render_legend()
+        self.render_scalebar()
+        self.dc.EndDrawing()
+
+    def render_frame(self):
+        """Render the frames for map and legend/scalebar."""
+
+        dc = self.dc
+        dc.SetPen(wx.BLACK_PEN)
+        dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+        # Dimension stuff
+        width, height = dc.GetSizeTuple()
+        mminx, mminy, mmaxx, mmaxy = self.destination_region
+
+        # Page Frame
+        dc.DrawRectangle(15,15,width-30, (mmaxy-mminy)+10)
+
+        # Map Frame
+        llx, lly, urx, ury = self.region
+        dc.DrawRectangle(mminx + self.shiftx, mminy + self.shifty, urx, ury)
+
+        # Legend Frame
+        dc.DrawRectangle(mmaxx+10,mminy,(width-20) - (mmaxx+10), mmaxy-mminy)
+
+        dc.DestroyClippingRegion()
+        dc.SetClippingRegion(mmaxx+10,mminy,
+                             (width-20) - (mmaxx+10), mmaxy-mminy)
+
+    def render_legend(self):
+        """Render the legend on the Map."""
+
+        previewer = ClassDataPreviewer()
+        dc = self.dc
+        dc.SetPen(wx.BLACK_PEN)
+        dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+        # Dimension stuff
+        width, height = dc.GetSizeTuple()
+        mminx, mminy, mmaxx, mmaxy = self.destination_region
+        textwidth, textheight = dc.GetTextExtent("0")
+        iconwidth  = textheight
+        iconheight = textheight
+        stepy = textheight+3
+        dx = 10
+        posx = mmaxx + 10 + 5   # 10 pix distance mapframe/legend frame,
+                                # 5 pix inside legend frame
+        posy = mminy + 5        # 5 pix inside legend frame
+
+        # Render the legend
+        dc.SetTextForeground(wx.BLACK)
+        if self.map.HasLayers():
+            layers = self.map.Layers()[:]
+            layers.reverse()
+            for l in layers:
+                if l.Visible():
+                    # Render title
+                    dc.DrawText(l.Title(), posx, posy)
+                    posy+=stepy
+                    if l.HasClassification():
+                        # Render classification
+                        clazz = l.GetClassification()
+                        shapeType = l.ShapeType()
+                        for g in clazz:
+                            if g.IsVisible():
+                                previewer.Draw(dc,
+                                    wx.Rect(posx+dx, posy,
+                                           iconwidth, iconheight),
+                                    g.GetProperties(), shapeType)
+                                dc.DrawText(g.GetDisplayText(),
+                                            posx+2*dx+iconwidth, posy)
+                                posy+=stepy
+
+    def render_scalebar(self):
+        """Render the scalebar."""
+
+        scalebar = ScaleBar(self.map)
+
+        # Dimension stuff
+        width, height = self.dc.GetSizeTuple()
+        mminx, mminy, mmaxx, mmaxy = self.destination_region
+
+        # Render the scalebar
+        scalebar.DrawScaleBar(self.scale, self.dc,
+                             (mmaxx+10+5, mmaxy-25),
+                             ((width-15-5) - (mmaxx+10+5),20)
+                            )
+        # 10 pix between map and legend frame, 5 pix inside legend frame
+        # 25 pix from the legend frame bottom line
+        # Width: 15 pix from DC border, 5 pix inside frame, 10, 5 as above
+        # Height: 20
+
+class PrinterRenderer(ExportRenderer):
+
+    # Printing as well as Export / Screen display only the visible layer.
+    honor_visibility = 1
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/resource.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/resource.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/resource.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,32 @@
+# Copyright (c) 2003 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Acess to UI-related resources"""
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: resource.py 2700 2006-09-18 14:27:02Z dpinte $
+
+
+import os
+import Thuban
+
+import wx
+
+
+bitmapdir = os.path.join(Thuban.__path__[0], os.pardir, "Resources", "Bitmaps")
+bitmap_extensions = {wx.BITMAP_TYPE_XPM: ".xpm",
+                     wx.BITMAP_TYPE_ANY: ""}
+
+def GetBitmapResource(file, type):
+    filename = os.path.join(bitmapdir, file) + bitmap_extensions[type]
+    return wx.Bitmap(filename, type)
+
+def GetImageResource(file, type):
+    filename = os.path.join(bitmapdir, file) + bitmap_extensions[type]
+    return wx.Image(filename, type)
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/scalebar.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/scalebar.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/scalebar.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,71 @@
+# Copyright (c) 2001, 2002 by Intevation GmbH
+# Authors:
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2700 $"
+
+from Thuban import _
+from Thuban.Model.scalebar import deriveInterval, roundInterval
+from Thuban.Model.proj import PROJ_UNITS_METERS
+
+import wx
+
+class ScaleBar:
+
+    def __init__(self, map):
+        self.map = map
+
+    def DrawScaleBar(self, scale, dc, position, size):
+        """Draw a scalebar on a given DC"""
+
+        # Only draw a legend if the corresponding map has a layer
+        if self.map is not None \
+            and self.map.projection is not None \
+            and len(self.map.layers) > 0 \
+            and scale > 0.0:
+
+            # We have a projection, draw the scalebar in bw
+            BlackPen = wx.BLACK_PEN
+            BlackBrush = wx.BLACK_BRUSH
+            BlackText = wx.BLACK
+
+            # Get the dimension
+            width, height = size
+            posx, posy    = position
+            l1width, l1height = dc.GetTextExtent("%d"%0)
+
+            # Make a first guess for the interval (to get the size we have 
+            # to reserve for the labels)
+            interval, unit = deriveInterval(width, scale)
+            l2width, l2height = dc.GetTextExtent("%d %s"%(interval,unit))
+            width = width - 4.0 - l1width/2.0 -l2width/2.0
+
+            # Having precised the width now the final interval can be calculated
+            interval, unit  = deriveInterval(width, scale)
+            interval, label = roundInterval(interval)
+
+            if interval > 0.0:
+                # We draw 2 rectangles with half the width
+                if unit == 'km':
+                    width = int(interval*1000.0*scale/2)
+                else:
+                    width = int(interval*scale/2)
+
+                dc.SetPen(BlackPen)
+
+                brush = wx.Brush(wx.WHITE, wx.SOLID)
+                dc.SetBrush(brush)
+                dc.DrawRectangle(posx+4,posy+2,width,8)
+
+                dc.SetBrush(BlackBrush)
+                dc.DrawRectangle(posx+width+4,posy+2,width,8)
+
+                dc.SetTextForeground(BlackText)
+                dc.DrawText("%d"%0, posx+ 4 - l1width/2, posy+12)
+
+                l2width, l2height = dc.GetTextExtent("%s %s"%(label, unit))
+                dc.DrawText("%s %s"%(interval, unit), posx+ 2*width+4 - l2width/2, posy + 12)
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/selection.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/selection.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/selection.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,168 @@
+# Copyright (c) 2001, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Selection handling
+"""
+
+__version__ = "$Revision: 2709 $"
+# $Source$
+# $Id: selection.py 2709 2006-10-03 09:34:51Z dpinte $
+
+from Thuban.Lib.connector import Publisher
+
+from messages import LAYER_SELECTED, SHAPES_SELECTED
+
+
+class Selection(Publisher):
+
+    """Manage the selection
+
+    The selection consists of a list of shape ids and the layer that
+    contains those shapes.
+
+    Messages issued by the selection:
+
+    LAYER_SELECTED -- A different layer has been selected or there was a
+                      layer selected and the selection has been cleared.
+
+                      Arguments: The newly selected layer or None if no
+                      layer is selected.
+
+    SHAPES_SELECTED -- The set of selected shapes has changed.
+
+                       Arguments: The newly selected layer or None if no
+                       layer is selected and a list with ids of the
+                       selected shapes. The list is empty if no shapes
+                       are selected.
+    """
+
+    def __init__(self):
+        """Initialize the selection
+
+        Initially nothing is selected so the selected layer is None and
+        the list of selected shapes is empty.
+        """
+        self.layer = None
+        self.shapes = []
+
+    def issue_messages(self, issue_layer, issue_shape):
+        """Internal: Issue SHAPES_SELECTED and LAYER_SELECTED messages
+
+        If the issue_layer argument is true, issue a LAYER_SELECTED
+        message. If issue_shape is true issue a SHAPES_SELECTED message.
+        """
+        if issue_layer:
+            self.issue(LAYER_SELECTED, self.layer)
+        if issue_shape:
+            self.issue(SHAPES_SELECTED, self.layer, self.SelectedShapes())
+
+    def ClearSelection(self):
+        """Unselect the currently selected shapes if any.
+
+        If there was a layer selected before the call, send a
+        LAYER_SELECTED message. If there were selected shapes before the
+        call, send a SHAPES_SELECTED message as well.
+        """
+        issue_layer = self.layer is not None
+        issue_shape = len(self.shapes) > 0
+
+        self.layer = None
+        self.shapes = []
+        self.issue_messages(issue_layer, issue_shape)
+
+    def SelectedLayer(self):
+        """Return the selected layer. If no layer is selected return None"""
+        return self.layer
+
+    def HasSelectedLayer(self):
+        """Return true iff a layer is currently selected"""
+        return self.layer is not None
+
+    def SelectedShapes(self):
+        """Return the ids of the selected shapes as a list.
+
+        The list is sorted in ascending order. If no shapes are selected
+        the list is empty.
+        """
+        return self.shapes
+
+    def HasSelectedShapes(self):
+        """Return true iff at least one shape is selected."""
+        return len(self.shapes) > 0
+
+    def SelectLayer(self, layer):
+        """Select the given layer.
+
+        If the layer is the currently selected layer, do nothing.
+        Ortherwise, issue a LAYER_SELECTED message and if there were
+        shapes selected preciously issue a SHAPES_SELECTED message as
+        well.
+        """
+        if self.layer is not layer:
+            self.layer = layer
+            issue_shape = len(self.shapes) > 0
+            self.shapes = []
+            self.issue_messages(1, issue_shape)
+
+    def SelectShapes(self, layer, shapes, add = 0):
+        """Select the shapes given in the list shapes in the given layer.
+
+        If the optional keyword parameter add is true, add the selected
+        shapes to the currently selected shapes if layer is the already
+        selected layer if any. If add is false (the default) make the
+        shapes in shapes the selected shapes.
+
+        If a different layer is selected afterwards issue a
+        LAYER_SELECTED message. If the set of selected shapes has
+        changed afterwards issue a SHAPES_SELECTED message.
+        """
+        # Turn the shapes explicitly into a list. This main purpose
+        # is that we get a mutable sequence that we can modify in place.
+        shapes = list(shapes)
+        shapes.sort()
+
+        if self.layer is not layer:
+            # If the layer is differen we can ignore the add parameter
+            # and we have to issue both messages.
+            self.layer = layer
+            self.shapes = shapes
+            issue_layer = issue_shape = 1
+        else:
+            # If the layer is differen we have to merge the ids if add
+            # is true, and we won't have to issue the LAYER_SELECTED
+            # message.
+            issue_layer = 0
+            if add:
+                # Merge the ids by creating a dict with the ids in
+                # self.shapes and in shapes as the keys. The use the sorted
+                # keys of the dict as the new shapes list.
+                set = {}
+                for i in self.shapes:
+                    set[i] = 1
+                for i in shapes:
+                    set[i] = 1
+                shapes = set.keys()
+                shapes.sort()
+            if self.shapes != shapes:
+                self.shapes = shapes
+                issue_shape = 1
+            else:
+                issue_shape = 0
+
+        self.issue_messages(issue_layer, issue_shape)
+
+    def AddShapes(self, layer, shapes):
+        """Add the shapes on layer to the selection.
+
+        If the layer is the already selected layer, add the shape ids in
+        shapes to the already selected shapes.
+
+        If the layer is not the already selected layer, make the layer
+        and shapes the selected layer and shapes.
+        """
+        self.SelectShapes(layer, shapes)

Added: packages/thuban/branches/upstream/current/Thuban/UI/sizers.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/sizers.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/sizers.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,72 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Custom Sizers"""
+
+__version__ = "$Revision: 2700 $"
+# $Source$
+# $Id: sizers.py 2700 2006-09-18 14:27:02Z dpinte $
+
+import wx
+
+class NotebookLikeSizer(wx.PySizer):
+
+    """Similar to a wxNotebookSizer but doesn't need a real notebook
+    """
+
+    def __init__(self):
+        wx.PySizer.__init__(self)
+        self.item_dict = {}
+
+    def Add(self, item):
+        """Add the item to the sizer.
+
+        The children added with Add must must be an object that has
+        Show() and Hide() methods
+        """
+        wx.PySizer.Add(self, item)
+
+    def Activate(self, item):
+        """Activate the item.
+
+        Call this item's Show method and the Hide method of all other
+        items. The item must have been added to the sizer with Add.
+        """
+        for child in self.GetChildren():
+            window = child.GetWindow()
+            if window is item:
+                window.Show()
+            else:
+                window.Hide()
+
+    def RecalcSizes(self):
+        """Set all children to the current size of the sizer
+
+        This method is automatically called by the wxWindows sizer
+        mechanism.
+        """
+        pos = self.GetPosition()
+        size  = self.GetSize()
+
+        for item in self.GetChildren():
+            item.SetDimension(pos, size)
+
+    def CalcMin(self):
+        """Return the maximum of the minimum sizes of the children.
+
+        This method is automatically called by the wxWindows sizer
+        mechanism.
+        """
+        widths = []
+        heights = []
+        for item in self.GetChildren():
+            size = item.CalcMin()
+            widths.append(size.width)
+            heights.append(size.height)
+        if widths:
+            return wx.Size(max(widths), max(heights))
+        return wx.Size(0, 0)

Added: packages/thuban/branches/upstream/current/Thuban/UI/tableview.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/tableview.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/tableview.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,648 @@
+# Copyright (c) 2001, 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2718 $"
+
+import os.path
+
+from Thuban import _
+
+import wx
+from wx import grid
+
+from Thuban.Lib.connector import Publisher
+from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
+     FIELDTYPE_STRING, table_to_dbf, table_to_csv
+from dialogs import ThubanFrame
+
+from messages import SHAPES_SELECTED, SESSION_REPLACED
+from Thuban.Model.messages import TABLE_REMOVED, MAP_LAYERS_REMOVED
+from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
+
+wx_value_type_map = {FIELDTYPE_INT: grid.GRID_VALUE_NUMBER,
+                     FIELDTYPE_DOUBLE: grid.GRID_VALUE_FLOAT,
+                     FIELDTYPE_STRING: grid.GRID_VALUE_STRING}
+
+ROW_SELECTED = "ROW_SELECTED"
+
+QUERY_KEY = 'S'
+
+class DataTable(grid.PyGridTableBase):
+
+    """Wrapper around a Thuban table object suitable for a wxGrid"""
+
+    def __init__(self, table = None):
+        grid.PyGridTableBase.__init__(self)
+        self.num_cols = 0
+        self.num_rows = 0
+        self.columns = []
+        self.table = None
+        self.SetTable(table)
+
+    def SetTable(self, table):
+        self.table = table
+        self.num_cols = table.NumColumns()
+        self.num_rows = table.NumRows()
+
+        self.columns = []
+        for i in range(self.num_cols):
+            col = table.Column(i)
+            self.columns.append((col.name, wx_value_type_map[col.type]))
+
+    #
+    # required methods for the wxPyGridTableBase interface
+    #
+
+    def GetNumberRows(self):
+        return self.num_rows
+
+    def GetNumberCols(self):
+        return self.num_cols
+
+    def IsEmptyCell(self, row, col):
+        return 0
+
+    # Get/Set values in the table.  The Python version of these
+    # methods can handle any data-type, (as long as the Editor and
+    # Renderer understands the type too,) not just strings as in the
+    # C++ version.
+    def GetValue(self, row, col):
+        try:
+            record = self.table.ReadRowAsDict(row, row_is_ordinal = 1)
+        except UnicodeError:
+            record = dict()
+            for (key, val) in self.table.ReadRowAsDict(row, \
+                              row_is_ordinal = 1).items():
+                if isinstance(val, str):
+                    record[key] = val.decode('iso-8859-1')
+                else:
+                    record[key] = val
+        return record[self.columns[col][0]]
+
+    def SetValue(self, row, col, value):
+        pass
+
+    #
+    # Some optional methods
+    #
+
+    # Called when the grid needs to display labels
+    def GetColLabelValue(self, col):
+        return self.columns[col][0]
+
+    # Called to determine the kind of editor/renderer to use by
+    # default, doesn't necessarily have to be the same type used
+    # nativly by the editor/renderer if they know how to convert.
+    def GetTypeName(self, row, col):
+        return self.columns[col][1]
+
+    # Called to determine how the data can be fetched and stored by the
+    # editor and renderer.  This allows you to enforce some type-safety
+    # in the grid.
+    def CanGetValueAs(self, row, col, typeName):
+        # perhaps we should allow conversion int->double?
+        return self.GetTypeName(row, col) == typeName
+
+    def CanSetValueAs(self, row, col, typeName):
+        return self.CanGetValueAs(row, col, typeName)
+
+
+    #
+    def RowIdToOrdinal(self, rowid):
+        """Return the ordinal of the row given by its id"""
+        return self.table.RowIdToOrdinal(rowid)
+
+    def RowOrdinalToId(self, ordinal):
+        """Return the id of the row given by its ordinal"""
+        return self.table.RowOrdinalToId(ordinal)
+
+
+class NullRenderer(grid.PyGridCellRenderer):
+
+    """Renderer that draws NULL as a gray rectangle
+
+    Other values are delegated to a normal renderer which is given as
+    the parameter to the constructor.
+    """
+
+    def __init__(self, non_null_renderer):
+        grid.PyGridCellRenderer.__init__(self)
+        self.non_null_renderer = non_null_renderer
+
+    def Draw(self, grid, attr, dc, rect, row, col, isSelected):
+        value = grid.table.GetValue(row, col)
+        if value is None:
+            dc.SetBackgroundMode(wx.SOLID)
+            dc.SetBrush(wx.Brush(wx.Colour(192, 192, 192), wx.SOLID))
+            dc.SetPen(wx.TRANSPARENT_PEN)
+            dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+        else:
+            self.non_null_renderer.Draw(grid, attr, dc, rect, row, col,
+                                        isSelected)
+
+    def GetBestSize(self, grid, attr, dc, row, col):
+        self.non_null_renderer.GetBestSize(grid, attr, dc, row, col)
+
+    def Clone(self):
+        return NullRenderer(self.non_null_renderer)
+
+
+class TableGrid(grid.Grid, Publisher):
+
+    """A grid view for a Thuban table
+
+    When rows are selected by the user the table issues ROW_SELECTED
+    messages. wx sends selection events even when the selection is
+    manipulated by code (instead of by the user) which usually lead to
+    ROW_SELECTED messages being sent in turn. Therefore sending messages
+    can be switched on and off with the allow_messages and
+    disallow_messages methods.
+    """
+
+    def __init__(self, parent, table = None):
+        grid.Grid.__init__(self, parent, -1)
+
+        self.allow_messages_count = 0
+
+        # keep track of which rows are selected.
+        self.rows = {}
+
+        self.table = DataTable(table)
+
+        # The second parameter means that the grid is to take ownership
+        # of the table and will destroy it when done. Otherwise you
+        # would need to keep a reference to it and call its Destroy
+        # method later.
+        self.SetTable(self.table, True)
+
+        #self.SetMargins(0,0)
+
+        # AutoSizeColumns would allow us to make the grid have optimal
+        # column widths automatically but it would cause a traversal of
+        # the entire table which for large .dbf files can take a very
+        # long time.
+        #self.AutoSizeColumns(False)
+
+        self.SetSelectionMode(grid.Grid.wxGridSelectRows)
+
+        self.ToggleEventListeners(True)
+        self.Bind(grid.EVT_GRID_RANGE_SELECT, self.OnRangeSelect)
+        self.Bind(grid.EVT_GRID_SELECT_CELL, self.OnSelectCell)
+
+        # Replace the normal renderers with our own versions which
+        # render NULL/None values specially
+        self.RegisterDataType(grid.GRID_VALUE_STRING,
+                              NullRenderer(grid.GridCellStringRenderer()), None)
+        self.RegisterDataType(grid.GRID_VALUE_NUMBER,
+                              NullRenderer(grid.GridCellNumberRenderer()), None)
+        self.RegisterDataType(grid.GRID_VALUE_FLOAT,
+                              NullRenderer(grid.GridCellFloatRenderer()), None)
+
+        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+
+    def OnDestroy(self, event):
+        Publisher.Destroy(self)
+
+    def SetTableObject(self, table):
+        self.table.SetTable(table)
+
+    def OnRangeSelect(self, event):
+        to_id = self.table.RowOrdinalToId
+        if self.handleSelectEvents:
+            self.rows = dict([(to_id(i), 0) for i in self.GetSelectedRows()])
+
+            # if we're selecting we need to include the selected range and
+            # make sure that the current row is also included, which may
+            # not be the case if you just click on a single row!
+            if event.Selecting():
+                for i in range(event.GetTopRow(), event.GetBottomRow() + 1):
+                    self.rows[to_id(i)] = 0
+                self.rows[to_id(event.GetTopLeftCoords().GetRow())] = 0
+
+            self.issue(ROW_SELECTED, self.rows.keys())
+
+        event.Skip()
+
+    def OnSelectCell(self, event):
+        to_id = self.table.RowOrdinalToId
+        if self.handleSelectEvents:
+            self.issue(ROW_SELECTED,
+                       [to_id(i) for i in self.GetSelectedRows()])
+        event.Skip()
+
+    def ToggleEventListeners(self, on):
+        self.handleSelectEvents = on
+
+    def GetNumberSelected(self):
+        return len(self.rows)
+
+    def disallow_messages(self):
+        """Disallow messages to be send.
+
+        This method only increases a counter so that calls to
+        disallow_messages and allow_messages can be nested. Only the
+        outermost calls will actually switch message sending on and off.
+        """
+        self.allow_messages_count += 1
+
+    def allow_messages(self):
+        """Allow messages to be send.
+
+        This method only decreases a counter so that calls to
+        disallow_messages and allow_messages can be nested. Only the
+        outermost calls will actually switch message sending on and off.
+        """
+        self.allow_messages_count -= 1
+
+    def issue(self, *args):
+        """Issue a message unless disallowed.
+
+        See the allow_messages and disallow_messages methods.
+        """
+        if self.allow_messages_count == 0:
+            Publisher.issue(self, *args)
+
+    def SelectRowById(self, rowid, do_select):
+        """Select row with the id rowid"""
+        self.SelectRow(self.table.RowIdToOrdinal(rowid), do_select)
+
+
+class LayerTableGrid(TableGrid):
+
+    """Table grid for the layer tables.
+
+    The LayerTableGrid is basically the same as a TableGrid but it's
+    selection is usually coupled to the selected object in the map.
+    """
+
+    def select_shapes(self, layer, shapes):
+        """Select the row corresponding to the specified shape and layer
+
+        If layer is not the layer the table is associated with do
+        nothing. If shape or layer is None also do nothing.
+        """
+        if layer is not None \
+            and layer.ShapeStore().Table() is self.table.table:
+
+            self.disallow_messages()
+            try:
+                self.ClearSelection()
+                if len(shapes) > 0:
+                    # keep track of the lowest id so we can make it the
+                    # first visible item
+                    first = -1
+
+                    to_ordinal = self.table.RowIdToOrdinal
+                    for shape in shapes:
+                        row = to_ordinal(shape)
+                        self.SelectRow(row, True)
+                        if row < first:
+                            first = row
+
+                    self.SetGridCursor(first, 0)
+                    self.MakeCellVisible(first, 0)
+            finally:
+                self.allow_messages()
+
+
+class TableFrame(ThubanFrame):
+
+    """Frame that displays a Thuban table in a grid view"""
+
+    def __init__(self, parent, name, title, table):
+        ThubanFrame.__init__(self, parent, name, title)
+        self.panel = wx.Panel(self, -1)
+
+        self.table = table
+        self.grid = self.make_grid(self.table)
+        self.app = self.parent.application
+        self.app.Subscribe(SESSION_REPLACED, self.close_on_session_replaced)
+        self.session = self.app.Session()
+        self.session.Subscribe(TABLE_REMOVED, self.close_on_table_removed)
+
+    def OnDestroy(self, event):
+        """Extend inherited method to unsubscribe messages"""
+        self.app.Unsubscribe(SESSION_REPLACED, self.close_on_session_replaced)
+        self.session.Unsubscribe(TABLE_REMOVED, self.close_on_table_removed)
+        ThubanFrame.OnDestroy(self, event)
+
+    def make_grid(self, table):
+        """Return the table grid to use in the frame.
+
+        The default implementation returns a TableGrid instance.
+        Override in derived classes to use different grid classes.
+        """
+        return TableGrid(self, table)
+
+    def close_on_session_replaced(self, *args):
+        """Subscriber for the SESSION_REPLACED messages.
+
+        The table frame is tied to a session so close the window when
+        the session changes.
+        """
+        self.Close()
+
+    def close_on_table_removed(self, table):
+        """Subscriber for the TABLE_REMOVED messages.
+
+        The table frame is tied to a particular table so close the
+        window when the table is removed.
+        """
+        if table is self.table:
+            self.Close()
+
+
+ID_QUERY = 4001
+ID_EXPORT = 4002
+ID_COMBOVALUE = 4003
+ID_EXPORTSEL = 4004
+
+class QueryTableFrame(TableFrame):
+
+    """Frame that displays a table in a grid view and offers user actions
+    selection and export
+
+    A QueryTableFrame is TableFrame whose selection is connected to the
+    selected object in a map.
+    """
+
+    def __init__(self, parent, name, title, table):
+        TableFrame.__init__(self, parent, name, title, table)
+
+        self.combo_fields = wx.ComboBox(self.panel, -1, style=wx.CB_READONLY)
+        self.choice_comp = wx.Choice(self.panel, -1,
+                              choices=["<", "<=", "==", "!=", ">=", ">"])
+        self.combo_value = wx.ComboBox(self.panel, ID_COMBOVALUE)
+        self.choice_action = wx.Choice(self.panel, -1,
+                                choices=[_("Replace Selection"),
+                                        _("Refine Selection"),
+                                        _("Add to Selection")])
+
+        button_query = wx.Button(self.panel, ID_QUERY, _("Query"))
+        button_export = wx.Button(self.panel, ID_EXPORT, _("Export"))
+        button_exportSel = wx.Button(self.panel, ID_EXPORTSEL, _("Export Selection"))
+        button_close = wx.Button(self.panel, wx.ID_CLOSE, _("Close"))
+
+        self.CreateStatusBar()
+
+        self.grid.SetSize((400, 200))
+
+        self.combo_value.Append("")
+        for i in range(table.NumColumns()):
+            name = table.Column(i).name
+            self.combo_fields.Append(name)
+            self.combo_value.Append(name)
+
+        # assume at least one field?
+        self.combo_fields.SetSelection(0)
+        self.combo_value.SetSelection(0)
+        self.choice_action.SetSelection(0)
+        self.choice_comp.SetSelection(0)
+
+        self.grid.Reparent(self.panel)
+
+        self.UpdateStatusText()
+
+        topBox = wx.BoxSizer(wx.VERTICAL)
+
+        sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1,
+                                  _("Selection")),
+                                  wx.HORIZONTAL)
+        sizer.Add(self.combo_fields, 1, wx.EXPAND|wx.ALL, 4)
+        sizer.Add(self.choice_comp, 0, wx.ALL, 4)
+        sizer.Add(self.combo_value, 1, wx.EXPAND|wx.ALL, 4)
+        sizer.Add(self.choice_action, 0, wx.ALL, 4)
+        sizer.Add(button_query, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
+        sizer.Add( (40, 20), 0, wx.ALL, 4)
+
+        topBox.Add(sizer, 0, wx.EXPAND|wx.ALL, 4)
+        topBox.Add(self.grid, 1, wx.EXPAND|wx.ALL, 0)
+
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        sizer.Add(button_export, 0, wx.ALL, 4)
+        sizer.Add(button_exportSel, 0, wx.ALL, 4)
+        sizer.Add( (60, 20), 1, wx.ALL|wx.EXPAND, 4)
+        sizer.Add(button_close, 0, wx.ALL|wx.ALIGN_RIGHT, 4)
+        topBox.Add(sizer, 0, wx.ALL | wx.EXPAND, 4)
+
+        self.panel.SetAutoLayout(True)
+        self.panel.SetSizer(topBox)
+        topBox.Fit(self.panel)
+        topBox.SetSizeHints(self.panel)
+
+        panelSizer = wx.BoxSizer(wx.VERTICAL)
+        panelSizer.Add(self.panel, 1, wx.EXPAND, 0)
+        self.SetAutoLayout(True)
+        self.SetSizer(panelSizer)
+        panelSizer.Fit(self)
+        panelSizer.SetSizeHints(self)
+
+        self.grid.SetFocus()
+
+        self.Bind(wx.EVT_BUTTON, self.OnQuery, id=ID_QUERY)
+        self.Bind(wx.EVT_BUTTON, self.OnExport, id=ID_EXPORT)
+        self.Bind(wx.EVT_BUTTON, self.OnExportSel, id=ID_EXPORTSEL)
+        self.Bind(wx.EVT_BUTTON, self.OnClose, id=wx.ID_CLOSE)
+        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown, self.grid)
+
+        self.grid.Subscribe(ROW_SELECTED, self.UpdateStatusText)
+
+    def UpdateStatusText(self, rows=None):
+        self.SetStatusText(_("%i rows (%i selected), %i columns")
+            % (self.grid.GetNumberRows(),
+               self.grid.GetNumberSelected(),
+               self.grid.GetNumberCols()))
+
+    def OnKeyDown(self, event):
+        """Catch query key from grid"""
+        if event.AltDown() and event.GetKeyCode() == ord(QUERY_KEY):
+            self.combo_fields.SetFocus()
+            self.combo_fields.refocus = True
+        else:
+            event.Skip()
+
+    def OnQuery(self, event):
+        ThubanBeginBusyCursor()
+        try:
+
+            text = self.combo_value.GetValue()
+            if self.combo_value.GetSelection() < 1 \
+                or self.combo_value.FindString(text) == -1:
+                value = text
+            else:
+                value = self.table.Column(text)
+
+            ids = self.table.SimpleQuery(
+                    self.table.Column(self.combo_fields.GetStringSelection()),
+                    self.choice_comp.GetStringSelection(),
+                    value)
+
+            choice = self.choice_action.GetSelection()
+
+            #
+            # what used to be nice code got became a bit ugly because
+            # each time we select a row a message is sent to the grid
+            # which we are listening for and then we send further 
+            # messages. 
+            #
+            # now, we disable those listeners select everything but
+            # the first item, reenable the listeners, and select
+            # the first element, which causes everything to be
+            # updated properly.
+            #
+            if ids:
+                self.grid.ToggleEventListeners(False)
+
+            if choice == 0:
+                # Replace Selection
+                self.grid.ClearSelection()
+            elif choice == 1:
+                # Refine Selection
+                sel = self.get_selected()
+                self.grid.ClearSelection()
+                ids = filter(sel.has_key, ids)
+            elif choice == 2:
+                # Add to Selection
+                pass
+
+            #
+            # select the rows (all but the first)
+            # 
+            firsttime = True
+            for id in ids:
+                if firsttime:
+                    firsttime = False
+                else:
+                    self.grid.SelectRowById(id, True)
+
+            self.grid.ToggleEventListeners(True)
+
+            #
+            # select the first row
+            #
+            if ids:
+                self.grid.SelectRowById(ids[0], True)
+
+        finally:
+            ThubanEndBusyCursor()
+
+    def doExport(self, onlySelected):
+
+        dlg = wx.FileDialog(self, _("Export Table To"), ".", "",
+                           _("DBF Files (*.dbf)|*.dbf|") +
+                           _("CSV Files (*.csv)|*.csv|") +
+                           _("All Files (*.*)|*.*"),
+                           wx.SAVE|wx.OVERWRITE_PROMPT)
+        if dlg.ShowModal() == wx.ID_OK:
+            filename = dlg.GetPath()
+            type = os.path.basename(filename).split('.')[-1:][0]
+            dlg.Destroy()
+
+            if onlySelected:
+                records = self.grid.GetSelectedRows()
+            else:
+                records = None
+
+            if type.upper() == "DBF":
+                table_to_dbf(self.table, filename, records)
+            elif type.upper() == 'CSV':
+                table_to_csv(self.table, filename, records)
+            else:
+                dlg = wx.MessageDialog(None, "Unsupported format: %s" % type,
+                                      "Table Export", wx.OK|wx.ICON_WARNING)
+                dlg.ShowModal()
+                dlg.Destroy()
+        else:
+            dlg.Destroy()
+
+    def OnExport(self, event):
+        self.doExport(False)
+
+    def OnExportSel(self, event):
+        self.doExport(True)
+
+    def OnClose(self, event):
+        TableFrame.OnClose(self, event)
+
+    def get_selected(self):
+        """Return a dictionary of the selected rows.
+
+        The dictionary has the indexes as keys."""
+        to_id = self.table.RowOrdinalToId
+        return dict([(to_id(i), 0) for i in self.grid.GetSelectedRows()])
+
+
+class LayerTableFrame(QueryTableFrame):
+
+    """Frame that displays a layer table in a grid view
+
+    A LayerTableFrame is a QueryTableFrame whose selection is connected to the
+    selected object in a map.
+    """
+
+    def __init__(self, parent, name, title, layer, table):
+        QueryTableFrame.__init__(self, parent, name, title, table)
+        self.layer = layer
+        self.grid.Subscribe(ROW_SELECTED, self.rows_selected)
+        self.parent.Subscribe(SHAPES_SELECTED, self.select_shapes)
+        self.map = self.parent.Map()
+        self.map.Subscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)
+
+        # if there is already a selection present, update the grid
+        # accordingly
+        sel = self.get_selected().keys()
+        for i in sel:
+            self.grid.SelectRowById(i, True)
+
+    def OnDestroy(self, event):
+        """Extend inherited method to unsubscribe messages"""
+        # There's no need to unsubscribe from self.grid's messages
+        # because it will get a DESTROY event too (since destroying the
+        # frame basically means that all child windows are also
+        # destroyed) and this it will clear all subscriptions
+        # automatically.  It may even have been destroyed already (this
+        # does happen on w2000 for instance) so calling any of its
+        # methods here would be an error.
+        self.parent.Unsubscribe(SHAPES_SELECTED, self.select_shapes)
+        self.map.Unsubscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)
+        QueryTableFrame.OnDestroy(self, event)
+
+    def make_grid(self, table):
+        """Override the derived method to return a LayerTableGrid.
+        """
+        return LayerTableGrid(self, table)
+
+    def get_selected(self):
+        """Override the derived method to return a dictionary of the selected
+        rows.
+        """
+        return dict([(i, 0) for i in self.parent.SelectedShapes()])
+
+    def select_shapes(self, layer, shapes):
+        """Subscribed to the SHAPES_SELECTED message.
+
+        If shapes contains exactly one shape id, select that shape in
+        the grid. Otherwise deselect all.
+        """
+        self.grid.select_shapes(layer, shapes)
+
+    def rows_selected(self, rows):
+        """Return the selected rows of the layer as they are returned
+        by Layer.SelectShapes().
+        """
+        if self.layer is not None:
+            self.parent.SelectShapes(self.layer, rows)
+
+    def map_layers_removed(self, *args):
+        """Receiver for the map's MAP_LAYERS_REMOVED message
+
+        Close the dialog if the layer whose table we're showing is not
+        in the map anymore.
+        """
+        if self.layer not in self.map.Layers():
+            self.Close()
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/tree.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/tree.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/tree.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,237 @@
+# Copyright (c) 2001, 2002, 2003 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+__version__ = "$Revision: 2700 $"
+
+from types import StringType, UnicodeType
+
+import wx
+
+from Thuban import _
+from Thuban.UI.common import Color2wxColour
+
+from Thuban.Model.color import Color
+
+from Thuban.Model.messages import CHANGED
+from Thuban.Model.layer import Layer
+from Thuban.Model.map import Map
+
+from dialogs import NonModalNonParentDialog
+from messages import SESSION_REPLACED, LAYER_SELECTED
+
+BMP_SIZE = 15
+
+class SessionTreeCtrl(wx.TreeCtrl):
+
+    """Widget to display a tree view of the session.
+
+    The tree view is created recursively from the session object. The
+    tree view calls the session's TreeInfo method which should return a
+    pair (<title>, <item>) where <title> ist the title of the session
+    item in the tree view and <items> is a list of objects to use as the
+    children of the session in the tree view.
+
+    The items list can contain three types of items:
+
+       1. a string. The string is used as the title for a leaf item in
+          the tree view.
+
+       2. an object with a TreeInfo method. This method is called and
+          should return a pair just like the session's TreeInfo method.
+
+       3. a pair (<title>, <item>) which is treated like the return
+          value of TreeInfo.
+    """
+
+    def __init__(self, parent, ID, mainwindow, app):
+
+        # Use the WANTS_CHARS style so the panel doesn't eat the Return key.
+        wx.TreeCtrl.__init__(self, parent, ID)
+
+        self.mainwindow = mainwindow
+        self.app = app
+        # boolean to indicate that we manipulate the selection ourselves
+        # so that we can ignore the selection events generated
+        self.changing_selection = 0
+
+        # Dictionary mapping layer id's to tree items
+        self.layer_to_item = {}
+
+        self.app.Subscribe(SESSION_REPLACED, self.session_changed)
+        self.mainwindow.Subscribe(LAYER_SELECTED, self.layer_selected)
+
+        # the session currently displayed in the tree
+        self.session = None
+
+
+        # pretend the session has changed to build the initial tree
+        self.session_changed()
+
+        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=self.GetId())
+
+    def unsubscribe_all(self):
+        if self.session is not None:
+            self.session.Unsubscribe(CHANGED, self.update_tree)
+            self.session = None
+        self.app.Unsubscribe(SESSION_REPLACED, self.session_changed)
+        self.mainwindow.Unsubscribe(LAYER_SELECTED, self.layer_selected)
+
+    def update_tree(self, *args):
+        """Clear and rebuild the tree"""
+        self.DeleteAllItems()
+        self.layer_to_item.clear()
+        self.image_list = wx.ImageList(BMP_SIZE, BMP_SIZE, False, 0)
+
+        bmp = wx.EmptyBitmap(BMP_SIZE, BMP_SIZE)
+        dc = wx.MemoryDC()
+        dc.SelectObject(bmp)
+        dc.SetBrush(wx.BLACK_BRUSH)
+        dc.Clear()
+        dc.SelectObject(wx.NullBitmap)
+
+        self.emptyImageIndex = \
+            self.image_list.AddWithColourMask(bmp, wx.Colour(0, 0, 0))
+
+        self.AssignImageList(self.image_list)
+
+        session = self.app.session
+        info = session.TreeInfo()
+        root = self.AddRoot(info[0], -1, -1, None)
+        self.SetItemImage(root, self.emptyImageIndex)
+        self.add_items(root, info[1])
+        self.Expand(root)
+        # select the selected layer
+        selected_layer = self.mainwindow.current_layer()
+        if selected_layer is not None:
+            # One would expect that the selected_layer's id is in
+            # layer_to_item at this point as we've just rebuilt that
+            # mapping completely. However, when a new session is loaded
+            # for instance, it can happen that the tree view is updated
+            # before the canvas's selection in which case selected_layer
+            # may be a layer of the old session.
+            item = self.layer_to_item.get(id(selected_layer))
+            if item is not None:
+                self.SelectItem(item)
+
+    def add_items(self, parent, items):
+
+        if items is None: return
+
+        for item in items:
+            if hasattr(item, "TreeInfo"):
+                # Supports the TreeInfo protocol
+                info = item.TreeInfo()
+                treeitem = self.AppendItem(parent, info[0], -1, -1, None)
+                self.SetItemImage(treeitem, self.emptyImageIndex)
+                self.SetPyData(treeitem, item)
+                self.add_items(treeitem, info[1])
+                self.Expand(treeitem)
+                if isinstance(item, Layer):
+                    self.layer_to_item[id(item)] = treeitem
+            elif isinstance(item, StringType) or \
+                 isinstance(item, UnicodeType):
+                # it's a string
+                treeitem = self.AppendItem(parent, item, -1, -1, None)
+                self.SetItemImage(treeitem, self.emptyImageIndex)
+            else:
+                # assume its a sequence (title, items)
+                if isinstance(item[1], Color):
+
+                    treeitem = self.AppendItem(parent, "(%s)" % item[0])
+
+                    bmp = wx.EmptyBitmap(BMP_SIZE, BMP_SIZE)
+                    brush = wx.Brush(Color2wxColour(item[1]), wx.SOLID)
+                    dc = wx.MemoryDC()
+                    dc.SelectObject(bmp)
+                    dc.SetBrush(brush)
+                    dc.Clear()
+                    dc.DrawRoundedRectangle(0, 0,
+                                            bmp.GetWidth(), bmp.GetHeight(),
+                                            4)
+                    dc.SelectObject(wx.NullBitmap)
+
+                    i = self.image_list.Add(bmp)
+                    self.SetItemImage(treeitem, i)
+                else:
+                    treeitem = self.AppendItem(parent, item[0], -1, -1, None)
+                    self.SetItemImage(treeitem, self.emptyImageIndex)
+                    self.add_items(treeitem, item[1])
+                self.Expand(treeitem)
+
+    def session_changed(self, *args):
+        new_session = self.app.session
+        # if the session has changed subscribe/unsubscribe
+        if self.session is not new_session:
+            if self.session is not None:
+                self.session.Unsubscribe(CHANGED, self.update_tree)
+            if new_session is not None:
+                new_session.Subscribe(CHANGED, self.update_tree)
+            self.session = new_session
+        self.update_tree()
+
+    def normalize_selection(self):
+        """Select the layer or map containing currently selected item"""
+        item = self.GetSelection()
+        while item.IsOk():
+            object = self.GetPyData(item)
+            if isinstance(object, Layer) or isinstance(object, Map):
+                break
+            item = self.GetItemParent(item)
+        else:
+            # No layer or map was found in the chain of parents, so
+            # there's nothing we can do.
+            return
+
+        self.changing_selection = 1
+        try:
+            self.SelectItem(item)
+        finally:
+            self.changing_selection = 0
+
+    def SelectedLayer(self):
+        """Return the layer object currently selected in the tree.
+        Return None if no layer is selected"""
+        layer = self.GetPyData(self.GetSelection())
+        if isinstance(layer, Layer):
+            return layer
+        return None
+
+    def OnSelChanged(self, event):
+        if self.changing_selection:
+            # we're changing the selection ourselves (probably through
+            # self.normalize_selection(). ignore the event.
+            return
+        self.normalize_selection()
+        # SelectedLayer returns None if no layer is selected. Since
+        # passing None to SelectLayer deselects the layer we can simply
+        # pass the result of SelectedLayer on in all cases
+        self.mainwindow.SelectLayer(self.SelectedLayer())
+
+    def layer_selected(self, layer):
+        item = self.layer_to_item.get(id(layer))
+        if item is not None and item != self.GetSelection():
+            self.SelectItem(item)
+
+
+class SessionTreeView(NonModalNonParentDialog):
+
+    """Non modal dialog showing the session as a tree"""
+
+    def __init__(self, parent, app, name):
+        NonModalNonParentDialog.__init__(self, parent, name, _("Session"))
+        self.tree = SessionTreeCtrl(self, -1, parent, app)
+
+    def OnClose(self, event):
+        NonModalNonParentDialog.OnClose(self, event)
+
+        # if there were a way to get notified when the tree control
+        # itself is destroyed we could use that to unsubscribe instead
+        # of doing it here. (EVT_WINDOW_DESTROY doesn't seem to sent at
+        # all)
+        self.tree.unsubscribe_all()
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/view.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/view.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/view.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,446 @@
+# opyright (c) 2001, 2002, 2003, 2004 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Frank Koormann <frank at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Classes for display of a map and interaction with it
+"""
+
+from __future__ import generators
+
+__version__ = "$Revision: 2718 $"
+# $Source$
+# $Id: view.py 2718 2007-01-05 23:43:49Z dpinte $
+
+import os.path
+import time
+import traceback
+
+import wx
+
+# Export related stuff
+if wx.Platform == '__WXMSW__':
+    from wx import MetaFileDC
+
+from Thuban import _
+
+from Thuban.Model.messages import MAP_LAYERS_CHANGED, LAYER_CHANGED, \
+     LAYER_VISIBILITY_CHANGED
+
+from renderer import ScreenRenderer, ExportRenderer, PrinterRenderer
+
+import labeldialog
+
+from viewport import ViewPort, PanTool, output_transform
+
+class CanvasPanTool(PanTool):
+
+    """The Canvas Pan Tool"""
+
+    def MouseMove(self, event):
+        if self.dragging:
+            PanTool.MouseMove(self, event)
+            sx, sy = self.start
+            x, y = self.current
+            width, height = self.view.GetSizeTuple()
+
+            bitmapdc = wx.MemoryDC()
+            bitmapdc.SelectObject(self.view.PreviewBitmap())
+
+            dc = self.view.drag_dc
+            dc.Blit(0, 0, width, height, bitmapdc, sx - x, sy - y)
+
+class MapPrintout(wx.Printout):
+
+    """
+    wxPrintout class for printing Thuban maps
+    """
+
+    def __init__(self, canvas, map, region, selected_layer, selected_shapes):
+        wx.Printout.__init__(self)
+        self.canvas = canvas
+        self.map = map
+        self.region = region
+        self.selected_layer = selected_layer
+        self.selected_shapes = selected_shapes
+
+    def GetPageInfo(self):
+        return (1, 1, 1, 1)
+
+    def HasPage(self, pagenum):
+        return pagenum == 1
+
+    def OnPrintPage(self, pagenum):
+        if pagenum == 1:
+            self.draw_on_dc(self.GetDC())
+
+    def draw_on_dc(self, dc):
+        width, height = self.GetPageSizePixels()
+        scale, offset, mapregion = output_transform(self.canvas.scale,
+                                                    self.canvas.offset,
+                                                    self.canvas.GetSizeTuple(),
+                                                    self.GetPageSizePixels())
+        resx, resy = self.GetPPIPrinter()
+        canvas_scale = self.canvas.scale
+        x, y, width, height = self.region
+        renderer = PrinterRenderer(dc, self.map, scale, offset,
+                                   region = (mapregion[0], mapregion[1],
+                                             (width/canvas_scale)*scale,
+                                             (height/canvas_scale)*scale),
+                                   resolution = resy,
+                                   destination_region = mapregion)
+        renderer.RenderMap(self.selected_layer, self.selected_shapes)
+        return True
+
+
+class MapCanvas(wx.Window, ViewPort):
+
+    """A widget that displays a map and offers some interaction"""
+
+    def __init__(self, parent, winid):
+        wx.Window.__init__(self, parent, winid)
+        ViewPort.__init__(self)
+
+        self.SetBackgroundColour(wx.Colour(255, 255, 255))
+
+        # the bitmap serving as backing store
+        self.bitmap = None
+        # the monochrome bitmap with the selection if any
+        self.selection_bitmap = None
+
+        self.backgroundColor = wx.WHITE_BRUSH
+
+        # The rendering iterator object. Used when rendering
+        # incrementally
+        self.render_iter = None
+
+        # subscribe the WX events we're interested in
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+        self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown)
+        self.Bind(wx.EVT_MIDDLE_UP, self.OnMiddleUp)
+        self.Bind(wx.EVT_MOTION, self.OnMotion)
+        self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+    def __del__(self):
+        wx.Window.__del__(self)
+        ViewPort.__del__(self)
+
+    def PreviewBitmap(self):
+        return self.bitmap
+
+    def PanTool(self):
+        """Start the canvas pan tool"""
+        self.SelectTool(CanvasPanTool(self))
+
+    def SetMap(self, map):
+        redraw_channels = (MAP_LAYERS_CHANGED, LAYER_CHANGED,
+                           LAYER_VISIBILITY_CHANGED)
+        if self.Map() is not None:
+            for channel in redraw_channels:
+                self.Map().Unsubscribe(channel, self.full_redraw)
+
+        ViewPort.SetMap(self, map)
+
+        if self.Map() is not None:
+            for channel in redraw_channels:
+                self.Map().Subscribe(channel, self.full_redraw)
+
+        # force a redraw. If map is not empty, it's already been called
+        # by FitMapToWindow but if map is empty it hasn't been called
+        # yet so we have to explicitly call it.
+        self.full_redraw()
+
+    def OnPaint(self, event):
+        dc = wx.PaintDC(self)
+        if self.Map() is not None and self.Map().HasLayers():
+            if self.bitmap is not None:
+                dc.BeginDrawing()
+                dc.DrawBitmap(self.bitmap, 0, 0)
+                if self.selection_bitmap is not None:
+                    dc.DrawBitmap(self.selection_bitmap, 0, 0, True)
+                dc.EndDrawing()
+        else:
+            # If we've got no map or if the map is empty, simply clear
+            # the screen.
+
+            # XXX it's probably possible to get rid of this. The
+            # background color of the window is already white and the
+            # only thing we may have to do is to call self.Refresh()
+            # with a true argument in the right places.
+            dc.BeginDrawing()
+            dc.SetBackground(self.backgroundColor)
+            dc.Clear()
+            dc.EndDrawing()
+
+    def OnIdle(self, event):
+        """Idle handler. Redraw the bitmap if necessary"""
+        if (self.Map() is not None
+            and (self.bitmap is None
+                 or self.render_iter is not None
+                 or (self.HasSelectedShapes()
+                     and self.selection_bitmap is None))):
+            event.RequestMore(self._do_redraw())
+
+    def _do_redraw(self):
+        """Redraw a bit and return whether this method has to be called again.
+
+        Called by OnIdle to handle the actual redraw. Redraw is
+        incremental for both the bitmap with the normal layers and the
+        bitmap with the selection.
+        """
+        finished = False
+        if self.render_iter is not None:
+            try:
+                if self.render_iter.next():
+                    # Redraw if the last preview redraw was some time
+                    # ago and the user is not currently dragging the
+                    # mouse because redrawing would interfere with what
+                    # the current tool is drawing on the window.
+                    if not self.dragging \
+                           and time.time() - self.render_last_preview > 0.5:
+                        client_dc = wx.ClientDC(self)
+                        client_dc.BeginDrawing()
+                        client_dc.DrawBitmap(self.bitmap, 0, 0)
+                        client_dc.EndDrawing()
+                        self.render_last_preview = time.time()
+                else:
+                    self.render_iter = None
+                    # Redraw if not dragging because redrawing would
+                    # interfere with what the current tool is drawing on
+                    # the window.
+                    if not self.dragging:
+                        self.redraw()
+                    finished = True
+            except StopIteration:
+                finished = True
+                self.render_iter = None
+            except:
+                finished = True
+                self.render_iter = None
+                traceback.print_exc()
+        else:
+            self.render_iter = self._render_iterator()
+            self.render_last_preview = time.time()
+        return not finished
+
+    def _render_iterator(self):
+        width, height = self.GetSizeTuple()
+        dc = wx.MemoryDC()
+
+        render_start = time.time()
+
+        if self.bitmap is None:
+            self.bitmap = wx.EmptyBitmap(width, height)
+            dc.SelectObject(self.bitmap)
+            dc.BeginDrawing()
+
+            dc.SetBackground(self.backgroundColor)
+            dc.Clear()
+
+            # draw the map into the bitmap
+            renderer = ScreenRenderer(dc, self.Map(), self.scale, self.offset,
+                                      (0, 0, width, height))
+            for cont in renderer.RenderMapIncrementally():
+                yield True
+
+            dc.EndDrawing()
+            dc.SelectObject(wx.NullBitmap)
+
+        if self.HasSelectedShapes() and self.selection_bitmap is None:
+            bitmap = wx.EmptyBitmap(width, height)
+            dc.SelectObject(bitmap)
+            dc.BeginDrawing()
+            dc.SetBackground(wx.WHITE_BRUSH)
+            dc.Clear()
+
+            renderer = ScreenRenderer(dc, self.Map(), self.scale, self.offset,
+                                      (0, 0, width, height))
+            layer = self.SelectedLayer()
+            shapes = self.selection.SelectedShapes()
+            for cont in renderer.draw_selection_incrementally(layer, shapes):
+                yield True
+
+            dc.EndDrawing()
+            dc.SelectObject(wx.NullBitmap)
+
+            bitmap.SetMask(wx.Mask(bitmap, wx.WHITE))
+            self.selection_bitmap = bitmap
+
+        yield False
+
+    def Export(self):
+
+        if hasattr(self, "export_path"):
+            export_path = self.export_path
+        else:
+            export_path="."
+        dlg = wx.FileDialog(self, _("Export Map"), export_path, "",
+                           "Enhanced Metafile (*.wmf)|*.wmf",
+                           wx.SAVE|wx.OVERWRITE_PROMPT)
+        if dlg.ShowModal() == wx.ID_OK:
+            self.export_path = os.path.dirname(dlg.GetPath())
+            dc = wx.MetaFileDC(dlg.GetPath())
+
+            scale, offset, mapregion = output_transform(self.scale,
+                                                        self.offset,
+                                                        self.GetSizeTuple(),
+                                                        dc.GetSizeTuple())
+
+            selected_layer = self.selection.SelectedLayer()
+            selected_shapes = self.selection.SelectedShapes()
+
+            width, height = self.GetSizeTuple()
+            renderer = ExportRenderer(dc, self.Map(), scale, offset,
+                                      region = (0, 0,
+                                                (width/self.scale)*scale,
+                                                (height/self.scale)*scale),
+                                      destination_region = mapregion)
+            renderer.RenderMap(selected_layer, selected_shapes)
+
+            dc.EndDrawing()
+            dc.Close()
+        dlg.Destroy()
+
+    def Print(self):
+        printer = wx.Printer()
+        width, height = self.GetSizeTuple()
+        selected_layer = self.selection.SelectedLayer()
+        selected_shapes = self.selection.SelectedShapes()
+
+        printout = MapPrintout(self, self.Map(), (0, 0, width, height),
+                               selected_layer, selected_shapes)
+        printer.Print(self, printout, True)
+        printout.Destroy()
+
+    def redraw(self, *args):
+        self.Refresh(False)
+
+    def full_redraw(self, *args):
+        self.bitmap = None
+        self.selection_bitmap = None
+        self.render_iter = None
+        self.redraw()
+
+    def redraw_selection(self, *args):
+        self.selection_bitmap = None
+        self.render_iter = None
+        self.redraw()
+
+    def map_projection_changed(self, map, old_proj):
+        ViewPort.map_projection_changed(self, map, old_proj)
+        self.full_redraw()
+
+    def layer_projection_changed(self, *args):
+        ViewPort.layer_projection_changed(self, args)
+        self.full_redraw()
+
+    def set_view_transform(self, scale, offset):
+        ViewPort.set_view_transform(self, scale, offset)
+        self.full_redraw()
+
+    def GetPortSizeTuple(self):
+        return self.GetSizeTuple()
+
+    def OnMiddleDown(self, event):
+        self.remembertool = self.tool
+        if self.Map() is not None and self.Map().HasLayers():
+            self.PanTool()
+            self.OnLeftDown(event)
+
+    def OnMiddleUp(self, event):
+        self.OnLeftUp(event)
+        if self.remembertool:
+            self.SelectTool(self.remembertool)
+
+    def OnLeftDown(self, event):
+        self.MouseLeftDown(event)
+        if self.tool is not None:
+            self.drag_dc = wx.ClientDC(self)
+            self.drag_dc.SetLogicalFunction(wx.INVERT)
+            self.drag_dc.SetBrush(wx.TRANSPARENT_BRUSH)
+            self.tool.Show(self.drag_dc)
+            self.CaptureMouse()
+            self.dragging = 1
+
+    def OnLeftUp(self, event):
+        """Handle EVT_LEFT_UP
+
+        Release the mouse if it was captured, if a tool is active call
+        its Hide method and call self.MouseLeftUp.
+        """
+        # It's important that ReleaseMouse is called before MouseLeftUp.
+        # MouseLeftUp may pop up modal dialogs which leads to an
+        # effectively frozen X session because the user can only
+        # interact with the dialog but the mouse is still grabbed by the
+        # canvas.
+        if self.dragging:
+            if self.HasCapture():
+                self.ReleaseMouse()
+            try:
+                self.tool.Hide(self.drag_dc)
+            finally:
+                self.drag_dc = None
+                self.dragging = 0
+        self.MouseLeftUp(event)
+
+    def OnMotion(self, event):
+        if self.dragging:
+            self.tool.Hide(self.drag_dc)
+
+        self.MouseMove(event)
+
+        if self.dragging:
+            self.tool.Show(self.drag_dc)
+
+    def OnLeaveWindow(self, event):
+        self.set_current_position(None)
+
+    def OnSize(self, event):
+        # the window's size has changed. We have to get a new bitmap. If
+        # we want to be clever we could try to get by without throwing
+        # everything away. E.g. when the window gets smaller, we could
+        # either keep the bitmap or create the new one from the old one.
+        # Even when the window becomes larger some parts of the bitmap
+        # could be reused.
+        self.full_redraw()
+
+    def shape_selected(self, layer, shape):
+        """Receiver for the SHAPES_SELECTED messages. Redraw the map."""
+        # The selection object takes care that it only issues
+        # SHAPES_SELECTED messages when the set of selected shapes has
+        # actually changed, so we can do a full redraw of the
+        # selection_bitmap unconditionally.
+        ViewPort.shape_selected(self, layer, shape)
+        self.redraw_selection()
+
+    def GetTextExtent(self, text):
+        dc = wx.ClientDC(self)
+        font = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL)
+        dc.SetFont(font)
+        return dc.GetTextExtent(text.decode('iso-8859-1'))
+
+    def LabelShapeAt(self, x, y, text=None):
+        """Add or remove a label at window position x, y.
+
+        If there's a label at the given position, remove it. Otherwise
+        determine the shape at the position, run the label dialog and
+        unless the user cancels the dialog, add a label.
+        """
+        layer, shape_index = self.find_shape_at(x, y, select_labels = 1)
+        if layer is None and shape_index is not None:
+            ViewPort.LabelShapeAt(self, x, y)
+        elif layer is not None:
+            text = labeldialog.run_label_dialog(self,
+                                                layer.ShapeStore().Table(),
+                                                shape_index)
+            ViewPort.LabelShapeAt(self, x, y, text)
+
+

Added: packages/thuban/branches/upstream/current/Thuban/UI/viewport.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/UI/viewport.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/UI/viewport.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1006 @@
+# Copyright (c) 2003-2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de> (2003, 2004)
+# Jonathan Coles <jonathan at intevation.de> (2003)
+# Jan-Oliver Wagner <jan at intevation.de> (2004)
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Classes for display of a map and interaction with it
+"""
+
+__version__ = "$Revision: 2710 $"
+# $Source$
+# $Id: viewport.py 2710 2006-10-10 08:31:44Z dpinte $
+
+import sys
+from math import hypot
+
+from wxproj import point_in_polygon_shape, shape_centroid
+
+from Thuban.Model.messages import MAP_PROJECTION_CHANGED, \
+     LAYER_PROJECTION_CHANGED, TITLE_CHANGED, \
+     MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED
+from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
+     SHAPETYPE_POINT, RAW_SHAPEFILE
+from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
+     ALIGN_LEFT, ALIGN_RIGHT
+from Thuban.Lib.connector import Publisher, Conduit
+from Thuban.Model.color import Transparent
+
+from selection import Selection
+
+from messages import LAYER_SELECTED, SHAPES_SELECTED, VIEW_POSITION, \
+     SCALE_CHANGED, MAP_REPLACED
+
+import hittest
+
+#
+#   The tools
+#
+
+class Tool:
+
+    """
+    Base class for the interactive tools
+    """
+
+    def __init__(self, view):
+        """Intitialize the tool. The view is the canvas displaying the map"""
+        self.view = view
+        self.start = self.current = None
+        self.dragging = 0
+        self.drawn = 0
+
+    def __del__(self):
+        del self.view
+
+    def Name(self):
+        """Return the tool's name"""
+        return ''
+
+    def drag_start(self, x, y):
+        self.start = self.current = x, y
+        self.dragging = 1
+
+    def drag_move(self, x, y):
+        self.current = x, y
+
+    def drag_stop(self, x, y):
+        self.current = x, y
+        self.dragging = 0
+
+    def Show(self, dc):
+        if not self.drawn:
+            self.draw(dc)
+        self.drawn = 1
+
+    def Hide(self, dc):
+        if self.drawn:
+            self.draw(dc)
+        self.drawn = 0
+
+    def draw(self, dc):
+        pass
+
+    def MouseDown(self, event):
+        self.drag_start(event.m_x, event.m_y)
+
+    def MouseMove(self, event):
+        if self.dragging:
+            self.drag_move(event.m_x, event.m_y)
+
+    def MouseUp(self, event):
+        if self.dragging:
+            self.drag_stop(event.m_x, event.m_y)
+
+    def Cancel(self):
+        self.dragging = 0
+
+
+class RectTool(Tool):
+
+    """Base class for tools that draw rectangles while dragging"""
+
+    def draw(self, dc):
+        sx, sy = self.start
+        cx, cy = self.current
+        dc.DrawRectangle(sx, sy, cx - sx, cy - sy)
+
+class ZoomInTool(RectTool):
+
+    """The Zoom-In Tool"""
+
+    def Name(self):
+        return "ZoomInTool"
+
+    def proj_rect(self):
+        """return the rectangle given by start and current in projected
+        coordinates"""
+        sx, sy = self.start
+        cx, cy = self.current
+        left, top = self.view.win_to_proj(sx, sy)
+        right, bottom = self.view.win_to_proj(cx, cy)
+        return (min(left, right), min(top, bottom),
+                max(left, right), max(top, bottom))
+
+    def MouseUp(self, event):
+        if self.dragging:
+            Tool.MouseUp(self, event)
+            sx, sy = self.start
+            cx, cy = self.current
+            if sx == cx or sy == cy:
+                # Just a mouse click or a degenerate rectangle. Simply
+                # zoom in by a factor of two
+                # FIXME: For a click this is the desired behavior but should we
+                # really do this for degenrate rectagles as well or
+                # should we ignore them?
+                self.view.ZoomFactor(2, center = (cx, cy))
+            else:
+                # A drag. Zoom in to the rectangle
+                self.view.FitRectToWindow(self.proj_rect())
+
+
+class ZoomOutTool(RectTool):
+
+    """The Zoom-Out Tool"""
+
+    def Name(self):
+        return "ZoomOutTool"
+
+    def MouseUp(self, event):
+        if self.dragging:
+            Tool.MouseUp(self, event)
+            sx, sy = self.start
+            cx, cy = self.current
+            if sx == cx or sy == cy:
+                # Just a mouse click or a degenerate rectangle. Simply
+                # zoom out by a factor of two.
+                # FIXME: For a click this is the desired behavior but should we
+                # really do this for degenrate rectagles as well or
+                # should we ignore them?
+                self.view.ZoomFactor(0.5, center = (cx, cy))
+            else:
+                # A drag. Zoom out to the rectangle
+                self.view.ZoomOutToRect((min(sx, cx), min(sy, cy),
+                                         max(sx, cx), max(sy, cy)))
+
+class PanTool(Tool):
+
+    """The Pan Tool"""
+
+    def Name(self):
+        return "PanTool"
+
+    def MouseMove(self, event):
+        if self.dragging:
+            Tool.MouseMove(self, event)
+
+    def MouseUp(self, event):
+        if self.dragging:
+            Tool.MouseUp(self, event)
+            sx, sy = self.start
+            cx, cy = self.current
+            self.view.Translate(cx - sx, cy - sy)
+
+class IdentifyTool(Tool):
+
+    """The "Identify" Tool"""
+
+    def Name(self):
+        return "IdentifyTool"
+
+    def MouseUp(self, event):
+        self.view.SelectShapeAt(event.m_x, event.m_y)
+
+
+class LabelTool(Tool):
+
+    """The "Label" Tool"""
+
+    def Name(self):
+        return "LabelTool"
+
+    def MouseUp(self, event):
+        self.view.LabelShapeAt(event.m_x, event.m_y)
+
+
+class ViewPort(Conduit):
+
+    """An abstract view of the main window"""
+
+    # Some messages that can be subscribed/unsubscribed directly through
+    # the MapCanvas come in fact from other objects. This is a dict
+    # mapping those messages to the names of the instance variables they
+    # actually come from. The delegation is implemented in the Subscribe
+    # and Unsubscribe methods
+    delegated_messages = {LAYER_SELECTED: "selection",
+                          SHAPES_SELECTED: "selection"}
+
+    # Methods delegated to some instance variables. The delegation is
+    # implemented in the __getattr__ method.
+    delegated_methods = {"SelectLayer": "selection",
+                         "SelectShapes": "selection",
+                         "SelectedLayer": "selection",
+                         "HasSelectedLayer": "selection",
+                         "HasSelectedShapes": "selection",
+                         "SelectedShapes": "selection"}
+
+    # Some messages are forwarded from the currently shown map.  This is
+    # simply a list of the channels to forward.  The _subscribe_map and
+    # _unsubscribe_map methods use this to handle the forwarding.
+    forwarded_map_messages = (LAYER_PROJECTION_CHANGED, TITLE_CHANGED,
+                              MAP_PROJECTION_CHANGED,
+                              MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED)
+
+    def __init__(self, size = (400, 300)):
+
+        self.size = size
+
+        # the map displayed in this canvas. Set with SetMap()
+        self.map = None
+
+        # scale and offset describe the transformation from projected
+        # coordinates to window coordinates.
+        self.scale = 1.0
+        self.offset = (0, 0)
+
+        # whether the user is currently dragging the mouse, i.e. moving
+        # the mouse while pressing a mouse button
+        self.dragging = 0
+
+        # the currently active tool
+        self.tool = None
+
+        # The current mouse position of the last OnMotion event or None
+        # if the mouse is outside the window.
+        self.current_position = None
+
+        # the selection
+        self.selection = Selection()
+        self.selection.Subscribe(SHAPES_SELECTED, self.shape_selected)
+
+        # keep track of which layers/shapes are selected to make sure we
+        # only redraw when necessary
+        self.last_selected_layer = None
+        self.last_selected_shape = None
+
+    def Destroy(self):
+        self._unsubscribe_map(self.map)
+        self.map = None
+        self.selection.Destroy()
+        self.tool = None
+
+    def Subscribe(self, channel, *args):
+        """Extend the inherited method to handle delegated messages.
+
+        If channel is one of the delegated messages call the appropriate
+        object's Subscribe method. Otherwise just call the inherited
+        method.
+        """
+        if channel in self.delegated_messages:
+            object = getattr(self, self.delegated_messages[channel])
+            object.Subscribe(channel, *args)
+        else:
+            Conduit.Subscribe(self, channel, *args)
+
+    def Unsubscribe(self, channel, *args):
+        """Extend the inherited method to handle delegated messages.
+
+        If channel is one of the delegated messages call the appropriate
+        object's Unsubscribe method. Otherwise just call the inherited
+        method.
+        """
+        if channel in self.delegated_messages:
+            object = getattr(self, self.delegated_messages[channel])
+            object.Unsubscribe(channel, *args)
+        else:
+            Conduit.Unsubscribe(self, channel, *args)
+
+    def __getattr__(self, attr):
+        if attr in self.delegated_methods:
+            return getattr(getattr(self, self.delegated_methods[attr]), attr)
+        raise AttributeError(attr)
+
+    def SetMap(self, map):
+        self._unsubscribe_map(self.map)
+        changed = self.map is not map
+        self.map = map
+        self.selection.ClearSelection()
+        self._subscribe_map(self.map)
+        self.FitMapToWindow()
+        self.issue(MAP_REPLACED)
+
+    def _subscribe_map(self, map):
+        """Internal: Subscribe to some of the map's messages"""
+        if map is not None:
+            map.Subscribe(LAYER_PROJECTION_CHANGED,
+                          self.layer_projection_changed)
+            map.Subscribe(MAP_PROJECTION_CHANGED,
+                          self.map_projection_changed)
+            for channel in self.forwarded_map_messages:
+                self.subscribe_forwarding(channel, map)
+
+    def _unsubscribe_map(self, map):
+        """
+        Internal: Unsubscribe from the messages subscribed to in _subscribe_map
+        """
+        if map is not None:
+            for channel in self.forwarded_map_messages:
+                self.unsubscribe_forwarding(channel, map)
+            map.Unsubscribe(MAP_PROJECTION_CHANGED,
+                            self.map_projection_changed)
+            map.Unsubscribe(LAYER_PROJECTION_CHANGED,
+                            self.layer_projection_changed)
+
+    def Map(self):
+        """Return the map displayed by this canvas or None if no map is shown
+        """
+        return self.map
+
+    def map_projection_changed(self, map, old_proj):
+        """Subscribed to the map's MAP_PROJECTION_CHANGED message
+
+        If the projection changes, the region shown is probably not
+        meaningful anymore in the new projection.  Therefore this method
+        tries to keep the same region visible as before.
+        """
+        proj = self.map.GetProjection()
+
+        bbox = None
+
+        if old_proj is not None and proj is not None and self.map.HasLayers():
+            width, height = self.GetPortSizeTuple()
+            llx, lly = self.win_to_proj(0, height)
+            urx, ury = self.win_to_proj(width, 0)
+            bbox = old_proj.InverseBBox((llx, lly, urx, ury))
+            bbox = proj.ForwardBBox(bbox)
+
+        if bbox is not None:
+            self.FitRectToWindow(bbox)
+        else:
+            self.FitMapToWindow()
+
+    def layer_projection_changed(self, *args):
+        """Subscribed to the LAYER_PROJECTION_CHANGED messages
+
+        This base-class implementation does nothing currently, but it
+        can be extended in derived classes to e.g. redraw the window.
+        """
+
+    def calc_min_max_scales(self, scale = None):
+        if scale is None:
+            scale = self.scale
+
+        llx, lly, urx, ury = bbox = self.map.ProjectedBoundingBox()
+        pwidth = float(urx - llx)
+        pheight = float(ury - lly)
+
+        # width/height of the window
+        wwidth, wheight = self.GetPortSizeTuple()
+
+        # The window coordinates used when drawing the shapes must fit
+        # into 16bit signed integers.
+        max_len = max(pwidth, pheight)
+        if max_len:
+            max_scale = 32767.0 / max_len
+        else:
+            # FIXME: What to do in this case? The bbox is effectively
+            # empty so any scale should work.
+            max_scale = scale
+
+        # The minimal scale is somewhat arbitrarily set to half that of
+        # the bbox fit into the window
+        scales = []
+        if pwidth:
+            scales.append(wwidth / pwidth)
+        if pheight:
+            scales.append(wheight / pheight)
+        if scales:
+            min_scale = 0.5 * min(scales)
+        else:
+            min_scale = scale
+
+        return min_scale, max_scale
+
+    def set_view_transform(self, scale, offset):
+        # width/height of the window
+        wwidth, wheight = self.GetPortSizeTuple()
+
+        # The window's center in projected coordinates assuming the new
+        # scale/offset
+        try:
+            pcenterx = (wwidth/2 - offset[0]) / scale
+            pcentery = (offset[1] - wheight/2) / scale
+        except ZeroDivisionError:
+            # scale was zero.  Probably a problem with the projections.
+            # printing an error message and return immediately. The user
+            # will hopefully be informed by the UI which displays a
+            # message for at least some of the projection problems.
+            print >>sys.stderr, "ViewPort.set_view_transform:", \
+                  "ZeroDivisionError, scale =", repr(scale)
+            return
+
+        min_scale, max_scale = self.calc_min_max_scales(scale)
+
+        if scale > max_scale:
+            scale = max_scale
+        elif scale < min_scale:
+            scale = min_scale
+
+        self.scale = scale
+
+        # determine new offset to preserve the center
+        self.offset = (wwidth/2 - scale * pcenterx,
+                       wheight/2 + scale * pcentery)
+        self.issue(SCALE_CHANGED, scale)
+
+    def GetPortSizeTuple(self):
+        return self.size
+
+    def proj_to_win(self, x, y):
+        """\
+        Return the point in  window coords given by projected coordinates x y
+        """
+        offx, offy = self.offset
+        return (self.scale * x + offx, -self.scale * y + offy)
+
+    def win_to_proj(self, x, y):
+        """\
+        Return the point in projected coordinates given by window coords x y
+        """
+        offx, offy = self.offset
+        return ((x - offx) / self.scale, (offy - y) / self.scale)
+
+    def VisibleExtent(self):
+        """Return the extent of the visible region in projected coordinates
+
+        The return values is a tuple (llx, lly, urx, ury) describing the
+        region.
+        """
+        width, height = self.GetPortSizeTuple()
+        llx, lly = self.win_to_proj(0, height)
+        urx, ury = self.win_to_proj(width, 0)
+        return (llx, lly, urx, ury)
+
+    def FitRectToWindow(self, rect):
+        """Fit the rectangular region given by rect into the window.
+
+        Set scale so that rect (in projected coordinates) just fits into
+        the window and center it.
+        """
+        width, height = self.GetPortSizeTuple()
+        llx, lly, urx, ury = rect
+        if llx == urx or lly == ury:
+            # zero width or zero height. Do Nothing
+            return
+        scalex = width / (urx - llx)
+        scaley = height / (ury - lly)
+        scale = min(scalex, scaley)
+        offx = 0.5 * (width - (urx + llx) * scale)
+        offy = 0.5 * (height + (ury + lly) * scale)
+        self.set_view_transform(scale, (offx, offy))
+
+    def FitMapToWindow(self):
+        """Fit the map to the window
+
+        Set the scale so that the map fits exactly into the window and
+        center it in the window.
+        """
+        if self.map is not None:
+            bbox = self.map.ProjectedBoundingBox()
+            if bbox is not None:
+                self.FitRectToWindow(bbox)
+
+    def FitLayerToWindow(self, layer):
+        """Fit the given layer to the window.
+
+        Set the scale so that the layer fits exactly into the window and
+        center it in the window.
+        """
+
+        bbox = layer.LatLongBoundingBox()
+        if bbox is not None:
+            proj = self.map.GetProjection()
+            if proj is not None:
+                bbox = proj.ForwardBBox(bbox)
+
+            if bbox is not None:
+                self.FitRectToWindow(bbox)
+
+    def FitSelectedToWindow(self):
+        layer = self.selection.SelectedLayer()
+        shapes = self.selection.SelectedShapes()
+
+        bbox = layer.ShapesBoundingBox(shapes)
+        if bbox is not None:
+            proj = self.map.GetProjection()
+            if proj is not None:
+                bbox = proj.ForwardBBox(bbox)
+
+            if bbox is not None:
+                if len(shapes) == 1 and layer.ShapeType() == SHAPETYPE_POINT:
+                    self.ZoomFactor(self.calc_min_max_scales()[1] / self.scale,
+                                    self.proj_to_win(bbox[0], bbox[1]))
+                else:
+                    self.FitRectToWindow(bbox)
+
+    def ZoomFactor(self, factor, center = None):
+        """Multiply the zoom by factor and center on center.
+
+        The optional parameter center is a point in window coordinates
+        that should be centered. If it is omitted, it defaults to the
+        center of the window
+        """
+        width, height = self.GetPortSizeTuple()
+        scale = self.scale * factor
+        offx, offy = self.offset
+        if center is not None:
+            cx, cy = center
+        else:
+            cx = width / 2
+            cy = height / 2
+        offset = (factor * (offx - cx) + width  / 2,
+                  factor * (offy - cy) + height / 2)
+        self.set_view_transform(scale, offset)
+
+    def ZoomOutToRect(self, rect):
+        """Zoom out to fit the currently visible region into rect.
+
+        The rect parameter is given in window coordinates
+        """
+        # determine the bbox of the displayed region in projected
+        # coordinates
+        width, height = self.GetPortSizeTuple()
+        llx, lly = self.win_to_proj(0, height - 1)
+        urx, ury = self.win_to_proj(width - 1, 0)
+
+        sx, sy, ex, ey = rect
+        scalex = (ex - sx) / (urx - llx)
+        scaley = (ey - sy) / (ury - lly)
+        scale = min(scalex, scaley)
+
+        offx = 0.5 * ((ex + sx) - (urx + llx) * scale)
+        offy = 0.5 * ((ey + sy) + (ury + lly) * scale)
+        self.set_view_transform(scale, (offx, offy))
+
+    def Translate(self, dx, dy):
+        """Move the map by dx, dy pixels"""
+        offx, offy = self.offset
+        self.set_view_transform(self.scale, (offx + dx, offy + dy))
+
+    def SelectTool(self, tool):
+        """Make tool the active tool.
+
+        The parameter should be an instance of Tool or None to indicate
+        that no tool is active.
+        """
+        self.tool = tool
+
+    def ZoomInTool(self):
+        """Start the zoom in tool"""
+        self.SelectTool(ZoomInTool(self))
+
+    def ZoomOutTool(self):
+        """Start the zoom out tool"""
+        self.SelectTool(ZoomOutTool(self))
+
+    def PanTool(self):
+        """Start the pan tool"""
+        self.SelectTool(PanTool(self))
+
+    def IdentifyTool(self):
+        """Start the identify tool"""
+        self.SelectTool(IdentifyTool(self))
+
+    def LabelTool(self):
+        """Start the label tool"""
+        self.SelectTool(LabelTool(self))
+
+    def CurrentTool(self):
+        """Return the name of the current tool or None if no tool is active"""
+        return self.tool and self.tool.Name() or None
+
+    def CurrentPosition(self):
+        """Return current position of the mouse in projected coordinates.
+
+        The result is a 2-tuple of floats with the coordinates. If the
+        mouse is not in the window, the result is None.
+        """
+        if self.current_position is not None:
+            x, y = self.current_position
+            return self.win_to_proj(x, y)
+        else:
+            return None
+
+    def set_current_position(self, event):
+        """Set the current position from event
+
+        Should be called by all events that contain mouse positions
+        especially EVT_MOTION. The event parameter may be None to
+        indicate the the pointer left the window.
+        """
+        if event is not None:
+            self.current_position = (event.m_x, event.m_y)
+        else:
+            self.current_position = None
+        self.issue(VIEW_POSITION)
+
+    def MouseLeftDown(self, event):
+        self.set_current_position(event)
+        if self.tool is not None:
+            self.tool.MouseDown(event)
+
+    def MouseLeftUp(self, event):
+        self.set_current_position(event)
+        if self.tool is not None:
+            self.tool.MouseUp(event)
+
+    def MouseMove(self, event):
+        self.set_current_position(event)
+        if self.tool is not None:
+            self.tool.MouseMove(event)
+
+    def shape_selected(self, layer, shape):
+        """Receiver for the SHAPES_SELECTED messages. Redraw the map."""
+        # The selection object takes care that it only issues
+        # SHAPES_SELECTED messages when the set of selected shapes has
+        # actually changed, so we can do a full redraw unconditionally.
+        # FIXME: We should perhaps try to limit the redraw to the are
+        # actually covered by the shapes before and after the selection
+        # change.
+        pass
+
+    def unprojected_rect_around_point(self, x, y, dist):
+        """Return a rect dist pixels around (x, y) in unprojected coordinates
+
+        The return value is a tuple (minx, miny, maxx, maxy) suitable a
+        parameter to a layer's ShapesInRegion method.
+        """
+        map_proj = self.map.projection
+        if map_proj is not None:
+            inverse = map_proj.Inverse
+        else:
+            inverse = None
+
+        xs = []
+        ys = []
+        for dx, dy in ((-1, -1), (1, -1), (1, 1), (-1, 1)):
+            px, py = self.win_to_proj(x + dist * dx, y + dist * dy)
+            if inverse:
+                px, py = inverse(px, py)
+            xs.append(px)
+            ys.append(py)
+        return (min(xs), min(ys), max(xs), max(ys))
+
+    def GetTextExtent(self, text):
+        """Return the extent of the text
+
+        This method must be implemented by derived classes. The return
+        value must have the same format as that of the GetTextExtent of
+        the wx DC objects.
+        """
+        raise NotImplementedError
+
+    def find_shape_at(self, px, py, select_labels = 0, searched_layer = None):
+        """Determine the shape at point px, py in window coords
+
+        Return the shape and the corresponding layer as a tuple (layer,
+        shapeid).
+
+        If the optional parameter select_labels is true (default false)
+        search through the labels. If a label is found return it's index
+        as the shape and None as the layer.
+
+        If the optional parameter searched_layer is given (or not None
+        which it defaults to), only search in that layer.
+        """
+
+        # First if the caller wants to select labels, search and return
+        # it if one is found. We must do this first because the labels
+        # are currently always drawn above all other layers.
+        if select_labels:
+            label = self._find_label_at(px, py)
+            if label is not None:
+                return None, label
+
+        #
+        # Search the normal layers
+        #
+
+        # Determine which layers to search. If the caller gave a
+        # specific layer, we only search that. Otherwise we have to
+        # search all visible vector layers in the map in reverse order.
+        if searched_layer:
+            layers = [searched_layer]
+        else:
+            layers = [layer for layer in self.map.Layers()
+                            if layer.HasShapes() and layer.Visible()]
+            layers.reverse()
+
+        # Search through the layers.
+        for layer in layers:
+            shape = self._find_shape_in_layer(layer, px, py)
+            if shape is not None:
+                return layer, shape
+        return None, None
+
+    def _find_shape_in_layer(self, layer, px, py):
+        """Internal: Return the id of the shape at (px, py) in layer
+
+        Return None if no shape is at those coordinates.
+        """
+
+        # For convenience, bind some methods and values to local
+        # variables.
+        map_proj = self.map.projection
+        if map_proj is not None:
+            forward = map_proj.Forward
+        else:
+            forward = None
+
+        scale = self.scale
+
+        offx, offy = self.offset
+
+        table = layer.ShapeStore().Table()
+        lc = layer.GetClassification()
+        field = layer.GetClassificationColumn()
+
+        # defaults to fall back on
+        filled = lc.GetDefaultFill() is not Transparent
+        stroked = lc.GetDefaultLineColor() is not Transparent
+
+        # Determine the ids of the shapes that overlap a tiny area
+        # around the point. For layers containing points we have to
+        # choose a larger size of the box we're testing against so
+        # that we take the size of the markers into account
+        # The size of the box is determined by the largest symbol
+        # of the corresponding layer.
+        maxsize = 1
+        if layer.ShapeType() == SHAPETYPE_POINT:
+            for group in layer.GetClassification():
+                props = group.GetProperties()
+                if props.GetSize() > maxsize:
+                    maxsize = props.GetSize()
+        box = self.unprojected_rect_around_point(px, py, maxsize)
+
+        # determine the function that does the hit test based on the layer
+        hittester = self._get_hit_tester(layer)
+
+        for shape in layer.ShapesInRegion(box):
+            if field:
+                record = table.ReadRowAsDict(shape.ShapeID())
+                group = lc.FindGroup(record[field])
+                props = group.GetProperties()
+                filled = props.GetFill() is not Transparent
+                stroked = props.GetLineColor() is not Transparent
+
+            if layer.ShapeType() == SHAPETYPE_POINT:
+                hit = hittester(layer, shape, filled, stroked,
+                                px, py, size = props.GetSize())
+            else:
+                hit = hittester(layer, shape, filled, stroked, px, py)
+
+            if hit:
+                return shape.ShapeID()
+        return None
+
+    def _get_hit_tester(self, layer):
+        """Internal: Return a hit tester suitable for the layer
+
+        The return value is a callable that accepts a shape object and
+        some other parameters and and returns a boolean to indicate
+        whether that shape has been hit. The callable is called like
+        this:
+
+           callable(layer, shape, filled, stroked, x, y)
+        """
+        store = layer.ShapeStore()
+        shapetype = store.ShapeType()
+
+        if shapetype == SHAPETYPE_POINT:
+            return self._hit_point
+        elif shapetype == SHAPETYPE_ARC:
+            return self._hit_arc
+        elif shapetype == SHAPETYPE_POLYGON:
+            return self._hit_polygon
+        else:
+            raise ValueError("Unknown shapetype %r" % shapetype)
+
+    def projected_points(self, layer, points):
+        """Return the projected coordinates of the points taken from layer.
+
+        Transform all the points in the list of lists of coordinate
+        pairs in points.
+
+        The transformation applies the inverse of the layer's projection
+        if any, then the map's projection if any and finally applies
+        self.scale and self.offset.
+
+        The returned list has the same structure as the one returned the
+        shape's Points method.
+        """
+        proj = self.map.GetProjection()
+        if proj is not None:
+            forward = proj.Forward
+        else:
+            forward = None
+        proj = layer.GetProjection()
+        if proj is not None:
+            inverse = proj.Inverse
+        else:
+            inverse = None
+        result = []
+        scale = self.scale
+        offx, offy = self.offset
+        for part in points:
+            result.append([])
+            for x, y in part:
+                if inverse:
+                    x, y = inverse(x, y)
+                if forward:
+                    x, y = forward(x, y)
+                result[-1].append((x * scale + offx,
+                                   -y * scale + offy))
+        return result
+
+    def _hit_point(self, layer, shape, filled, stroked, px, py, size = 5):
+        """Internal: return whether a click at (px,py) hits the point shape
+
+        The filled and stroked parameters determine whether the shape is
+        assumed to be filled or stroked respectively.
+
+        size -- defines the size of the point symbol. For the hitting
+                test it is assumed the symbol is a circle of this size
+                (radius).
+        """
+        x, y = self.projected_points(layer, shape.Points())[0][0]
+        return hypot(px - x, py - y) < size and (filled or stroked)
+
+    def _hit_arc(self, layer, shape, filled, stroked, px, py):
+        """Internal: return whether a click at (px,py) hits the arc shape
+
+        The filled and stroked parameters determine whether the shape is
+        assumed to be filled or stroked respectively.
+        """
+        if not stroked:
+            return 0
+        points = self.projected_points(layer, shape.Points())
+        return hittest.arc_hit(points, px, py)
+
+    def _hit_polygon(self, layer, shape, filled, stroked, px, py):
+        """Internal: return whether a click at (px,py) hits the polygon shape
+
+        The filled and stroked parameters determine whether the shape is
+        assumed to be filled or stroked respectively.
+        """
+        points = self.projected_points(layer, shape.Points())
+        hit = hittest.polygon_hit(points, px, py)
+        if filled:
+            return bool(hit)
+        return stroked and hit < 0
+
+    def _find_label_at(self, px, py):
+        """Internal: Find the label at (px, py) and return its index
+
+        Return None if no label is hit.
+        """
+        map_proj = self.map.projection
+        if map_proj is not None:
+            forward = map_proj.Forward
+        else:
+            forward = None
+        scale = self.scale
+        offx, offy = self.offset
+
+        labels = self.map.LabelLayer().Labels()
+        if labels:
+            for i in range(len(labels) - 1, -1, -1):
+                label = labels[i]
+                x = label.x
+                y = label.y
+                text = label.text
+                if forward:
+                    x, y = forward(x, y)
+                x = x * scale + offx
+                y = -y * scale + offy
+                width, height = self.GetTextExtent(text)
+                if label.halign == ALIGN_LEFT:
+                    # nothing to be done
+                    pass
+                elif label.halign == ALIGN_RIGHT:
+                    x = x - width
+                elif label.halign == ALIGN_CENTER:
+                    x = x - width/2
+                if label.valign == ALIGN_TOP:
+                    # nothing to be done
+                    pass
+                elif label.valign == ALIGN_BOTTOM:
+                    y = y - height
+                elif label.valign == ALIGN_CENTER:
+                    y = y - height/2
+                if x <= px < x + width and y <= py <= y + height:
+                    return i
+        return None
+
+    def SelectShapeAt(self, x, y, layer = None):
+        """\
+        Select and return the shape and its layer at window position (x, y)
+
+        If layer is given, only search in that layer. If no layer is
+        given, search through all layers.
+
+        Return a tuple (layer, shapeid). If no shape is found, return
+        (None, None).
+        """
+        layer, shape = result = self.find_shape_at(x, y, searched_layer=layer)
+        # If layer is None, then shape will also be None. We don't want
+        # to deselect the currently selected layer, so we simply select
+        # the already selected layer again.
+        if layer is None:
+            layer = self.selection.SelectedLayer()
+            shapes = []
+        else:
+            shapes = [shape]
+        self.selection.SelectShapes(layer, shapes)
+        return result
+
+    def LabelShapeAt(self, x, y, text = None):
+        """Add or remove a label at window position x, y.
+
+        If there's a label at the given position, remove it. Otherwise
+        determine the shape at the position and add a label.
+
+        Return True is an action was performed, False otherwise.
+        """
+        label_layer = self.map.LabelLayer()
+        layer, shape_index = self.find_shape_at(x, y, select_labels = 1)
+        if layer is None and shape_index is not None:
+            # a label was selected
+            label_layer.RemoveLabel(shape_index)
+            return True
+        elif layer is not None and text:
+            (x, y, halign, valign)  = layer.GetLabelPosFromShape(self.map, \
+                                                             shape_index)
+            label_layer.AddLabel(x, y, text,
+                                 halign = halign, valign = valign)
+            return True
+        return False
+
+def output_transform(canvas_scale, canvas_offset, canvas_size, device_extend):
+    """Calculate dimensions to transform canvas content to output device."""
+    width, height = device_extend
+
+    # Only 80 % of the with are available for the map
+    width = width * 0.8
+
+    # Define the distance of the map from DC border
+    distance = 20
+
+    if height < width:
+        # landscape
+        map_height = height - 2*distance
+        map_width = map_height
+    else:
+        # portrait, recalibrate width (usually the legend width is too
+        # small
+        width = width * 0.9
+        map_height = width - 2*distance
+        map_width = map_height
+
+    mapregion = (distance, distance,
+                 distance+map_width, distance+map_height)
+
+    canvas_width, canvas_height = canvas_size
+
+    scalex = map_width / (canvas_width/canvas_scale)
+    scaley = map_height / (canvas_height/canvas_scale)
+    scale = min(scalex, scaley)
+    canvas_offx, canvas_offy = canvas_offset
+    offx = scale*canvas_offx/canvas_scale
+    offy = scale*canvas_offy/canvas_scale
+
+    return scale, (offx, offy), mapregion

Added: packages/thuban/branches/upstream/current/Thuban/__init__.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/__init__.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/__init__.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,132 @@
+# Copyright (c) 2001, 2003, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Jan-Oliver Wagner <jan at intevation.de>
+# Bernhard Reiter <bernhard at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+import os
+
+# Thuban Message Translation
+#
+# This is somewhat tricky. On the one hand we want to use the wx
+# facilities because that way the standard wx messages are also
+# translated and we get automatic conversion of encodings so the we can
+# use e.g. an UTF po/mo file in a Latin 1 environment. OTOH, we do not
+# want to import the wxPython modules at all when running the test suite
+# because otherwise the test suite would require a working X server
+# connection.
+#
+# Therefore this module only provides the hooks for installing the
+# correct translation function with a default translation function that
+# does nothing and simply returns the string it gets as argument.
+#
+# The front end to the installed translation function is _ (see it's
+# doc-string).
+#
+# The Thuban.UI module is responsible for installing the wx translation
+# function. It must take care to install the translation function as
+# early as possible, i.e. when Thuban/UI/__init__.py is executed so that
+# strings translated at module import time are translated (this also
+# means that a program built on top of Thuban and which uses Thuban.UI
+# should start by importing Thuban.UI before any other Thuban module.
+#
+# At the same time Thuban/UI/__init__.py should not import any wxPython
+# module unless it really has to install the translation function, i.e.
+# when no other translation function has already been installed. That
+# way the test suite can override the wx translation by installing its
+# own translation function before importing anything from Thuban.UI and
+# actually before importing anything but the Thuban module itself.
+
+# Thedirectory holding the translation files (actually they're in
+# language specific subdirectories of _message_dir)
+_message_dir = os.path.join(os.path.dirname(__file__), os.pardir, "Resources",
+                            "Locale")
+
+def _(s):
+    """Return a localized version of the the string s
+
+    This is the function to use in the sources to translate strings and
+    it simply delegates the translation to the installable translation
+    function. It's done this way so that _ may be imported with 'from
+    Thuban import _' even when the correct translation function hasn't
+    been installed yet.
+    """
+    return _translation_function(s)
+
+def gettext_identity(s):
+    """Default gettext implementation which returns the string as is"""
+    return s
+
+_translation_function = gettext_identity
+
+def translation_function_installed():
+    """Return whether a translation function has been installed."""
+    return _translation_function is not gettext_identity
+
+def install_translation_function(function):
+    """Install function as the translation function
+
+    If a translation has already been installed that is not the default
+    implementation (gettext_identity) do nothing.
+    """
+    global _translation_function
+    if not translation_function_installed():
+        _translation_function = function
+
+
+
+# String representation in Thuban
+#
+# Thuban has an internal representation for textual data that all text
+# that comes into Thuban has to be converted into.  Any text written by
+# Thuban has to be converted to whatever is needed by the output device.
+#
+# Currently, the internal representation is usually a byte-string in a
+# particuler encoding.  For more details see the file
+# Doc/technotes/string_representation.txt.
+
+# The encoding to use for the internal string representation.  Usually
+# it's a string with the encoding name to use when converting between
+# Python byte-strings and unicode objects.  The special value "unicode"
+# means the use unicode objects as the internal representation.
+_internal_encoding = None
+
+def internal_from_unicode(unistr):
+    """Return Thuban's internal representation for the unicode object unistr"""
+    if _internal_encoding != "unicode":
+        # we use replace so that we don't get exceptions when the
+        # conversion can't be done properly.
+        return unistr.encode(_internal_encoding, "replace")
+    else:
+        return unistr
+
+def unicode_from_internal(s):
+    """Return the unicode object for the string s in internal representation"""
+    if _internal_encoding != "unicode":
+        return unicode(s, _internal_encoding)
+    else:
+        return s
+
+
+def set_internal_encoding(encoding):
+    """Set the encoding to use for the internal string representation
+
+    The parameter should be the name of an encoding known to Python so
+    that it can be used with e.g. the encode method of unicode objects.
+    As a special case it can be the string 'unicode' to indicate that
+    the internal representation are unicode objects.
+    """
+    global _internal_encoding
+    _internal_encoding = encoding
+
+    # and now let us test, if we can go back and forth
+    # it is better to complain now than to have runtime problems later
+    unicode_from_internal(internal_from_unicode(u''))
+
+def get_internal_encoding():
+    """Return the encoding used for Thuban's internal string representation."""
+    global _internal_encoding
+    return _internal_encoding

Added: packages/thuban/branches/upstream/current/Thuban/version.py
===================================================================
--- packages/thuban/branches/upstream/current/Thuban/version.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/Thuban/version.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,203 @@
+# Copyright (C) 2002, 2003, 2004 by Intevation GmbH
+# Authors:
+# Thomas Koester <tkoester at intevation.de>
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""
+Thuban version information
+"""
+
+__version__ = "$Revision: 2729 $"
+# $Source$
+# $Id: version.py 2729 2007-02-20 10:52:38Z bernhard $
+
+
+# Note that this file defines the version number of Thuban for the about
+# dialog.
+
+# The thuban version string is build from two values, thuban_branch and
+# thuban_release.  If release is "cvs" the code is from a non-released
+# cvs version and the version string is built from the branch, the
+# release and an approximation of the date (e.g. the most recent date of
+# the ChangeLog file or the most recent modification time of a source
+# file).  Otherwise the string is build from the branch and the release.
+# E.g. given
+#
+#  thuban_branch = "1.1"
+#  thuban_release = "svn"
+#
+# the version string will be "Thuban 1.1 svn-20040224" (obviously the
+# actual date might differ :) ).  OTOH, given
+#
+#  thuban_branch = "1.0"
+#  thuban_release = "1"
+#
+# the version string will be "Thuban 1.0.1"
+#
+
+thuban_branch = "1.2"
+thuban_release = "0"
+
+
+
+import sys, os, os.path
+import time
+from string import split
+
+from Thuban import  _
+from Thuban.Lib.version import make_tuple
+
+if __name__ == "__main__":
+    import sys
+    __file__ = sys.argv[0]
+
+def is_relevant_file(file):
+    """check if a file is relevant for determining the current version"""
+    extensions = ['.py', '.xpm', '.c', '.h']
+    return os.path.isfile(file) and os.path.splitext(file)[1] in extensions
+
+def visit(args, dirname, names):
+    """helper for os.path.walk; save mtime of newest file for this directory"""
+    files = filter(is_relevant_file,
+                   [os.path.join(dirname, file) for file in names])
+    args['max'] = max([args['max']] + map(os.path.getmtime, files))
+
+def get_date(format):
+    """strftime formatted mtime of the newest relevant file"""
+    dir = os.path.dirname(os.path.abspath(__file__))
+    args = {'max': 0}
+    os.path.walk(dir, visit, args)
+    return time.strftime(format, time.localtime(args['max']))
+
+def get_changelog_date():
+    changelog = os.path.join(os.path.dirname(__file__), os.pardir, "ChangeLog")
+    try:
+        file = open(changelog, "r")
+        line = file.readline()
+        file.close() 
+    except:
+        return ""
+    return 'ChangeLog %s' % line.split(" ")[0]
+
+
+# 
+# Fill in versions with the different versions of the libraries
+# that Thuban is using or requires (only if those libraries are
+# available.
+#
+
+versions = {}
+
+if thuban_release == "svn":
+    version = '%s %s-%s' % (thuban_branch, thuban_release, get_date('%Y%m%d'))
+    longversion = '%s\n%s' % (version, get_changelog_date())
+else:
+    version = thuban_branch + "." + thuban_release
+    longversion = 'Release Version ' + version
+
+versions['thuban'] = version
+versions['thuban-long'] = longversion
+
+# wxPython
+
+from wx import __version__ as wxPython_version
+versions['wxPython'] = wxPython_version
+versions['wxPython-tuple'] = make_tuple(wxPython_version)
+
+# Python
+versions['python'] = "%d.%d.%d" % sys.version_info[:3]
+versions['python-tuple'] = sys.version_info[:3]
+
+# PySQLite
+try:
+    from pysqlite2 import dbapi2 as sqlite
+except ImportError:
+    import sqlite
+versions['pysqlite'] = sqlite.version
+versions['pysqlite-tuple'] = make_tuple(sqlite.version)
+
+# SQLite
+try:
+    from pysqlite2._sqlite import sqlite_version
+    versions['sqlite'] = sqlite_version
+    versions['sqlite-tuple'] = make_tuple(sqlite_version)
+except ImportError:
+    from _sqlite import sqlite_version
+    versions['sqlite'] = sqlite_version()
+    versions['sqlite-tuple'] = make_tuple(sqlite_version())
+
+# GDAL
+from  Thuban.Model.resource import has_gdal_support
+if has_gdal_support():
+    from gdalwarp import get_gdal_version
+    versions['gdal'] = get_gdal_version()
+    versions['gdal-tuple'] = make_tuple(get_gdal_version())
+
+from wxproj import get_proj_version, get_gtk_version, get_wx_version
+
+# GTK
+gtk_ver = get_gtk_version()
+if gtk_ver:
+    versions['gtk'] = ".".join(map(str, gtk_ver))
+    versions['gtk-tuple'] = gtk_ver
+
+# PROJ
+proj_ver = get_proj_version()
+if proj_ver:
+    versions['proj'] = ".".join(map(str, proj_ver))
+    versions['proj-tuple'] = proj_ver
+
+wxproj_wx_version = get_wx_version()
+versions['wxproj-wx'] = ".".join(map(str, wxproj_wx_version))
+versions['wxproj-wx-tuple'] = wxproj_wx_version
+
+
+# psycopg/postgis
+import Thuban.Model.postgisdb
+if Thuban.Model.postgisdb.has_postgis_support():
+    v = Thuban.Model.postgisdb.psycopg_version()
+    versions['psycopg'] = v
+    versions['psycopg-tuple'] = make_tuple(v)
+
+def verify_versions():
+    """Verify that Thuban is using the correct versions of libraries.
+
+    Returns a non-empty list of strings indicating which libraries
+    are wrong, or the empty list if everthing is ok.
+    """
+
+    #
+    # The 'name' below must correspong to an mapping in 'versions'.
+    # There must also exist a 'name'-tuple mapping.
+    #
+    #         title           name       version
+    list = [["Python",      "python",   (2, 2, 1)],
+            ["wxPython",    "wxPython", (2, 4, 0)],
+            ["SQLite",      "sqlite",   (2, 8, 0)],
+            ["PySQLite",    "pysqlite", (0, 4, 1)],
+            ["PROJ",        "proj",     (4, 4, 5)],
+            ["GTK",         "gtk",      (1, 2, 3)],
+            ["GDAL",        "gdal",     (1, 1, 8)]]
+
+    errors = []
+    for title, name, version in list:
+        tup = versions.get("%s-tuple" % name, None)
+        if tup and tup < version:
+            errors.append(_("%s %s < %s") % \
+                          (title, versions[name], ".".join(map(str, version))))
+
+    # Check whether the wxWindows version of wxPython and thuban's
+    # wxproj module match.  If they don't match, segfaults are likely.
+    if versions["wxproj-wx-tuple"] != versions["wxPython-tuple"][:3]:
+        errors.append(_("Thuban was compiled with wx %(wxproj-wx)s"
+                        " but wxPython is %(wxPython)s")
+                      % versions)
+
+    return errors
+
+if __name__ == "__main__":
+    print longversion
+

Added: packages/thuban/branches/upstream/current/devtools/create_epsg.py
===================================================================
--- packages/thuban/branches/upstream/current/devtools/create_epsg.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/devtools/create_epsg.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,56 @@
+# Copyright (c) 2003 by Intevation GmbH
+# Authors:
+# Jan-Oliver Wagner <jan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Convert the epsg file of proj into a python .proj file.
+
+Call it like:
+$ python create_epsg.py > epsg.proj
+
+This tool assumes the original file of proj ('epsg') to
+be present in the standard location of a system wide
+installation, i.e. in /usr/share/proj/epsg.
+If it is somewhere else, just adapt the path in the code
+below.
+
+The entries in the source file look like this:
+
+# Anguilla 1957 / British West Indies Grid
+<200> +proj=tmerc +lat_0=0.000000000 +lon_0=-62.000000000 +k=0.999500 +x_0=40000 0.000 +y_0=0.000 +ellps=clrk80 +units=m  no_defs <>
+"""
+
+__version__ = "$Revision: 1800 $"
+
+# this function is copied from Thuban/Model/xmlwriter.py
+def escape(data):
+    """Escape &, \", ', <, and > in a string of data.
+    """
+    data = data.replace("&", "&amp;")
+    data = data.replace("<", "&lt;")
+    data = data.replace(">", "&gt;")
+    data = data.replace('"', "&quot;")
+    data = data.replace("'", "&apos;")
+    return data
+
+print '<?xml version="1.0" encoding="UTF-8"?>'
+print '<!DOCTYPE projfile SYSTEM "projectionlist.dtd">'
+print '<projectionlist>'
+
+epsg = open('/usr/share/proj/epsg', 'r').readlines()
+
+for line in epsg:
+    if line[0] == '#':
+        title = line[2:-1]
+    if line[0] == '<':
+        elements = line.split(' ')
+        epsg_nr = elements[0][1:-1]
+        print '    <projection epsg="%s" name="%s">' % (epsg_nr, escape(title))
+        for p in elements[1:-3]:
+            print '        <parameter value="%s"/>' % escape(p[1:])
+        print '    </projection>'
+
+print '</projectionlist>'

Added: packages/thuban/branches/upstream/current/libraries/pyprojection/LICENSE
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyprojection/LICENSE	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyprojection/LICENSE	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,27 @@
+Projection.i: SWIG interface file for PROJ.4 projection library.
+
+Copyright (c) 2001 Meridian Environmental Technology, Inc
+All rights reserved.
+
+Author: Douglas K. Rand <rand at meridian-enviro.com>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.

Added: packages/thuban/branches/upstream/current/libraries/pyprojection/MANIFEST.in
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyprojection/MANIFEST.in	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyprojection/MANIFEST.in	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,2 @@
+include *.i
+include *.txt Makefile *.pth

Added: packages/thuban/branches/upstream/current/libraries/pyprojection/Projection.i
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyprojection/Projection.i	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyprojection/Projection.i	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,229 @@
+// This looks most like -*- c -*- code
+
+//
+// Projection.i: SWIG interface file for PROJ.4 projection library.
+//
+// Copyright (c) 2001 Meridian Environmental Technology, Inc
+// All rights reserved.
+//
+// Author: Douglas K. Rand <rand at meridian-enviro.com>
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+//
+
+
+%module Projection
+%{
+#include <projects.h>
+
+    // We wrap the PJ structure in our own so we can keep the
+    // type of units the user wants to operate in along.
+    typedef enum {DEGREES, RADIANS} Units;
+    typedef struct {
+	Units units;
+	PJ *proj;
+    } Projection;
+%}
+
+%include typemaps.i
+%include constraints.i
+%include array.i
+
+typedef enum {DEGREES, RADIANS} Units;
+
+// Because that stupid pj_init() function requires a count of the args,
+// we have to do a typemap for EACH language terminating it with a null
+// so we can count the items in our wrapper.  Sigh.
+%typemap(python, in) char **argv {
+  /* Check if is a list */ 
+  if (PyList_Check($source)) { 
+    int size = PyList_Size($source); 
+    int i = 0; 
+    $target = (char **) malloc((size+1)*sizeof(char *)); 
+    for (i = 0; i < size; i++) { 
+      PyObject *o = PyList_GetItem($source,i); 
+      if (PyString_Check(o)) 
+	$target[i] = PyString_AsString(PyList_GetItem($source,i)); 
+      else { 
+	PyErr_SetString(PyExc_TypeError,"list must contain strings"); 
+	free($target); 
+	return NULL; 
+      } 
+    } 
+    $target[i] = 0; 
+  } else { 
+    PyErr_SetString(PyExc_TypeError,"not a list"); return NULL; 
+  }
+}
+
+// Free up the argv structure created above
+%typemap(python, freearg) char **argv { 
+  free((char *) $source);
+}
+
+/* Assign the pointer to a local variable */
+%typemap(python, ignore) double *outvalue(double temp) {
+    $target = &temp;
+}
+
+// This tells SWIG to treat an double * argument with name 'outvalue' as 
+// an output value. We'll append the value to the current result which 
+// is guaranteed to be a List object by SWIG.
+%typemap(python,argout) double *outvalue { 
+  PyObject *o; 
+  o = PyFloat_FromDouble(*$source); 
+  if ((!$target) || ($target == Py_None)) { 
+    $target = o; 
+  } else { 
+    if (!PyList_Check($target)) { 
+      PyObject *o2 = $target; 
+      $target = PyList_New(0); 
+      PyList_Append($target,o2); 
+      Py_XDECREF(o2); 
+    } 
+    PyList_Append($target,o); 
+    Py_XDECREF(o); 
+  } 
+}
+
+//%typemap(perl5, argout) double *outvalue {
+//    $target = sv_newmortal();
+//    sv_setnv($target, *$source);
+//    argvi++;
+//}
+
+/* Assign the pointer to a local variable */
+%typemap(python,in) double *outvalue {
+  static double junk;
+  $target = &junk;
+}
+
+//%typemap(perl5, in) double *outvalue {
+//    static double junk;
+//    $target = &junk;
+//}
+
+
+/* Exception handler for the Projection constructor */
+%typemap(python,except) Projection * {
+    /* Use pj_get_errno_ref to access the pj_errno because directly
+     * accessing pj_errno doesn't work on windows if the proj library is
+     * in a DLL */
+    *pj_get_errno_ref() = 0;
+    $function;
+    if (!$source)
+    {
+	/* FIXME: There's a case where $source is NULL and pj_errno is
+	 * not set, namely when memory allocation of the Projection
+	 * struct fails. */
+	SWIG_exception(SWIG_IOError, pj_strerrno(*pj_get_errno_ref()));
+    }
+}
+
+
+typedef struct {
+    Units	 units;
+    PJ		*proj;
+
+    %addmethods {
+	Projection(char **argv, Units units = DEGREES);
+	~Projection();
+	void Forward(double lat, double lon, double *outvalue, double *outvalue);
+	void Inverse(double u, double v, double *outvalue, double *outvalue);
+
+	PyObject * cobject() {
+	    return PyCObject_FromVoidPtr(self->proj, NULL);
+	}
+
+
+	/* The __del__ method generated by the old SWIG version we're
+	 * tries to access self.thisown which may not be set at all when
+	 * there was an exception during construction.  Therefore we
+	 * override it with our own version.
+	 * FIXME: It would be better to upgrade to a newer SWIG version
+	 * or to get rid of SWIG entirely.
+	 */
+	%pragma(python) addtoclass = "
+    def __del__(self,Projectionc=Projectionc):
+        if getattr(self, 'thisown', 0):
+            Projectionc.delete_Projection(self)
+    "
+
+    }
+} Projection;
+
+%{
+    // Make a brand new projection
+    Projection *new_Projection(char **argv, Units units) {
+	int argc = 0;
+	char **p;
+	PJ *proj;
+	Projection *pj = NULL;
+	
+	for(p = argv; p != NULL && *p != NULL; p++) argc++;
+	proj = pj_init(argc, argv);
+	if(proj != NULL) {
+	    pj = (Projection *) malloc(sizeof(Projection));
+	    pj->units = units;
+	    pj->proj = proj;
+	}
+	return pj;
+    }
+
+    // Get rid of a projection
+    void delete_Projection(Projection *self) {
+	if(self != NULL) {
+	    if(self->proj != NULL)
+		pj_free(self->proj);
+	    free(self);  
+	} 
+    }
+
+    // Do a forward (lat/lon --> world) translation
+    void Projection_Forward(Projection *self, double lat, double lon, double *u, double *v) {
+	projUV latlon, result;
+	latlon.u = lat;
+	latlon.v = lon;
+	if(self->units == DEGREES) {
+	    latlon.u *= DEG_TO_RAD;
+	    latlon.v *= DEG_TO_RAD;
+	}
+	result = pj_fwd(latlon, self->proj);
+	*u = result.u;
+	*v = result.v;
+    }
+
+    // Do a reverse (world --> lat/lon) translation
+    void Projection_Inverse(Projection *self, double u, double v, double *lat, double *lon) {
+	projUV world, result;
+	world.u = u;
+	world.v = v;
+	result = pj_inv(world, self->proj);
+	if(self->units == DEGREES) {
+	    result.u *= RAD_TO_DEG;
+	    result.v *= RAD_TO_DEG;
+	}
+	*lat = result.u;
+	*lon = result.v;
+    }
+%}

Added: packages/thuban/branches/upstream/current/libraries/pyprojection/Projection.py
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyprojection/Projection.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyprojection/Projection.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,93 @@
+# This file was created automatically by SWIG.
+import Projectionc
+class Projection:
+    def __init__(self,*args):
+        self.this = apply(Projectionc.new_Projection,args)
+        self.thisown = 1
+
+    def __del__(self,Projectionc=Projectionc):
+        if self.thisown == 1 :
+            Projectionc.delete_Projection(self)
+    def Forward(*args):
+        val = apply(Projectionc.Projection_Forward,args)
+        return val
+    def Inverse(*args):
+        val = apply(Projectionc.Projection_Inverse,args)
+        return val
+    def cobject(*args):
+        val = apply(Projectionc.Projection_cobject,args)
+        return val
+    __setmethods__ = {
+        "units" : Projectionc.Projection_units_set,
+        "proj" : Projectionc.Projection_proj_set,
+    }
+    def __setattr__(self,name,value):
+        if (name == "this") or (name == "thisown"): self.__dict__[name] = value; return
+        method = Projection.__setmethods__.get(name,None)
+        if method: return method(self,value)
+        self.__dict__[name] = value
+    __getmethods__ = {
+        "units" : Projectionc.Projection_units_get,
+        "proj" : Projectionc.Projection_proj_get,
+    }
+    def __getattr__(self,name):
+        method = Projection.__getmethods__.get(name,None)
+        if method: return method(self)
+        raise AttributeError,name
+    def __repr__(self):
+        return "<C Projection instance at %s>" % (self.this,)
+    
+    def __del__(self,Projectionc=Projectionc):
+        if getattr(self, 'thisown', 0):
+            Projectionc.delete_Projection(self)
+    
+class ProjectionPtr(Projection):
+    def __init__(self,this):
+        self.this = this
+        self.thisown = 0
+        self.__class__ = Projection
+
+
+
+
+
+#-------------- FUNCTION WRAPPERS ------------------
+
+int_array = Projectionc.int_array
+
+int_destroy = Projectionc.int_destroy
+
+int_get = Projectionc.int_get
+
+int_set = Projectionc.int_set
+
+double_array = Projectionc.double_array
+
+double_destroy = Projectionc.double_destroy
+
+double_get = Projectionc.double_get
+
+double_set = Projectionc.double_set
+
+float_array = Projectionc.float_array
+
+float_destroy = Projectionc.float_destroy
+
+float_get = Projectionc.float_get
+
+float_set = Projectionc.float_set
+
+string_array = Projectionc.string_array
+
+string_destroy = Projectionc.string_destroy
+
+string_get = Projectionc.string_get
+
+string_set = Projectionc.string_set
+
+
+
+#-------------- VARIABLE WRAPPERS ------------------
+
+DEGREES = Projectionc.DEGREES
+RADIANS = Projectionc.RADIANS

Added: packages/thuban/branches/upstream/current/libraries/pyprojection/Projection_wrap.c
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyprojection/Projection_wrap.c	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyprojection/Projection_wrap.c	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1549 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3u-20020503-1857 (Alpha 5)
+ * 
+ * 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
+ * changes to this file unless you know what you are doing--modify the SWIG 
+ * interface file instead. 
+ * ----------------------------------------------------------------------------- */
+
+#define SWIGPYTHON
+/***********************************************************************
+ * common.swg
+ *
+ *     This file contains generic SWIG runtime support for pointer
+ *     type checking as well as a few commonly used macros to control
+ *     external linkage.
+ *
+ * Author : David Beazley (beazley at cs.uchicago.edu)
+ *
+ * Copyright (c) 1999-2000, The University of Chicago
+ * 
+ * This file may be freely redistributed without license or fee provided
+ * this copyright message remains intact.
+ ************************************************************************/
+
+#include <string.h>
+
+#if defined(_WIN32) || defined(__WIN32__)
+#       if defined(_MSC_VER)
+#               if defined(STATIC_LINKED)
+#                       define SWIGEXPORT(a) a
+#               else
+#                       define SWIGEXPORT(a) __declspec(dllexport) a
+#               endif
+#       else
+#               if defined(__BORLANDC__)
+#                       define SWIGEXPORT(a) a _export
+#               else
+#                       define SWIGEXPORT(a) a
+#       endif
+#endif
+#else
+#       define SWIGEXPORT(a) a
+#endif
+
+#ifdef SWIG_GLOBAL
+#define SWIGRUNTIME(a) SWIGEXPORT(a)
+#else
+#define SWIGRUNTIME(a) static a
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct swig_type_info {
+  char  *name;                 
+  void *(*converter)(void *);
+  char  *str;
+  struct swig_type_info  *next;
+  struct swig_type_info  *prev;
+} swig_type_info;
+
+#ifdef SWIG_NOINCLUDE
+SWIGEXPORT(swig_type_info *) SWIG_TypeRegister(swig_type_info *);
+SWIGEXPORT(swig_type_info *) SWIG_TypeCheck(char *c, swig_type_info *);
+SWIGEXPORT(void *) SWIG_TypeCast(swig_type_info *, void *);
+#else
+
+static swig_type_info *swig_type_list = 0;
+
+/* Register a type mapping with the type-checking */
+SWIGRUNTIME(swig_type_info *)
+SWIG_TypeRegister(swig_type_info *ti)
+{
+  swig_type_info *tc, *head, *ret, *next;
+  /* Check to see if this type has already been registered */
+  tc = swig_type_list;
+  while (tc) {
+    if (strcmp(tc->name, ti->name) == 0) {
+      /* Already exists in the table.  Just add additional types to the list */
+      head = tc;
+      next = tc->next;
+      goto l1;
+    }
+    tc = tc->prev;
+  }
+  head = ti;
+  next = 0;
+
+  /* Place in list */
+  ti->prev = swig_type_list;
+  swig_type_list = ti;
+
+  /* Build linked lists */
+ l1:
+  ret = head;
+  tc = ti + 1;
+  /* Patch up the rest of the links */
+  while (tc->name) {
+    head->next = tc;
+    tc->prev = head;
+    head = tc;
+    tc++;
+  }
+  head->next = next;
+  return ret;
+}
+
+/* Check the typename */
+SWIGRUNTIME(swig_type_info *) 
+SWIG_TypeCheck(char *c, swig_type_info *ty)
+{
+  swig_type_info *s;
+  if (!ty) return 0;        /* Void pointer */
+  s = ty->next;             /* First element always just a name */
+  while (s) {
+    if (strcmp(s->name,c) == 0) {
+      if (s == ty->next) return s;
+      /* Move s to the top of the linked list */
+      s->prev->next = s->next;
+      if (s->next) {
+	s->next->prev = s->prev;
+      }
+      /* Insert s as second element in the list */
+      s->next = ty->next;
+      if (ty->next) ty->next->prev = s;
+      ty->next = s;
+      return s;
+    }
+    s = s->next;
+  }
+  return 0;
+}
+
+/* Cast a pointer (needed for C++ inheritance */
+SWIGRUNTIME(void *) 
+SWIG_TypeCast(swig_type_info *ty, void *ptr) 
+{
+  if ((!ty) || (!ty->converter)) return ptr;
+  return (*ty->converter)(ptr);
+}
+
+/* Search for a swig_type_info structure */
+SWIGRUNTIME(void *)
+SWIG_TypeQuery(const char *name) {
+  swig_type_info *ty = swig_type_list;
+  while (ty) {
+    if (ty->str && (strcmp(name,ty->str) == 0)) return ty;
+    if (ty->name && (strcmp(name,ty->name) == 0)) return ty;
+    ty = ty->prev;
+  }
+  return 0;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+/***********************************************************************
+ * python.swg
+ *
+ *     This file contains the runtime support for Python modules
+ *     and includes code for managing global variables and pointer
+ *     type checking.
+ *
+ * Author : David Beazley (beazley at cs.uchicago.edu)
+ ************************************************************************/
+
+#include <stdlib.h>
+#include "Python.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SWIG_PY_INT     1
+#define SWIG_PY_FLOAT   2
+#define SWIG_PY_STRING  3
+#define SWIG_PY_POINTER 4
+
+/* Constant information structure */
+typedef struct swig_const_info {
+    int type;
+    char *name;
+    long lvalue;
+    double dvalue;
+    void   *pvalue;
+    swig_type_info **ptype;
+} swig_const_info;
+
+#ifdef SWIG_NOINCLUDE
+
+SWIGEXPORT(PyObject *)        SWIG_newvarlink();
+SWIGEXPORT(void)              SWIG_addvarlink(PyObject *, char *, PyObject *(*)(void), int (*)(PyObject *));
+SWIGEXPORT(int)               SWIG_ConvertPtr(PyObject *, void **, swig_type_info *, int);
+SWIGEXPORT(void)              SWIG_MakePtr(char *c, void *, swig_type_info *);
+SWIGEXPORT(PyObject *)        SWIG_NewPointerObj(void *, swig_type_info *);
+SWIGEXPORT(void)              SWIG_InstallConstants(PyObject *d, swig_const_info constants[]);
+
+#else
+
+/* -----------------------------------------------------------------------------
+ * global variable support code.
+ * ----------------------------------------------------------------------------- */
+
+typedef struct swig_globalvar {   
+  char       *name;                  /* Name of global variable */
+  PyObject *(*get_attr)(void);       /* Return the current value */
+  int       (*set_attr)(PyObject *); /* Set the value */
+  struct swig_globalvar *next;
+} swig_globalvar;
+
+typedef struct swig_varlinkobject {
+  PyObject_HEAD
+  swig_globalvar *vars;
+} swig_varlinkobject;
+
+static PyObject *
+swig_varlink_repr(swig_varlinkobject *v) {
+  v = v;
+  return PyString_FromString("<Global variables>");
+}
+
+static int
+swig_varlink_print(swig_varlinkobject *v, FILE *fp, int flags) {
+  swig_globalvar  *var;
+  flags = flags;
+  fprintf(fp,"Global variables { ");
+  for (var = v->vars; var; var=var->next) {
+    fprintf(fp,"%s", var->name);
+    if (var->next) fprintf(fp,", ");
+  }
+  fprintf(fp," }\n");
+  return 0;
+}
+
+static PyObject *
+swig_varlink_getattr(swig_varlinkobject *v, char *n) {
+  swig_globalvar *var = v->vars;
+  while (var) {
+    if (strcmp(var->name,n) == 0) {
+      return (*var->get_attr)();
+    }
+    var = var->next;
+  }
+  PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+  return NULL;
+}
+
+static int
+swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) {
+  swig_globalvar *var = v->vars;
+  while (var) {
+    if (strcmp(var->name,n) == 0) {
+      return (*var->set_attr)(p);
+    }
+    var = var->next;
+  }
+  PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+  return 1;
+}
+
+statichere PyTypeObject varlinktype = {
+  PyObject_HEAD_INIT(0)              
+  0,
+  "swigvarlink",                      /* Type name    */
+  sizeof(swig_varlinkobject),         /* Basic size   */
+  0,                                  /* Itemsize     */
+  0,                                  /* Deallocator  */ 
+  (printfunc) swig_varlink_print,     /* Print        */
+  (getattrfunc) swig_varlink_getattr, /* get attr     */
+  (setattrfunc) swig_varlink_setattr, /* Set attr     */
+  0,                                  /* tp_compare   */
+  (reprfunc) swig_varlink_repr,       /* tp_repr      */    
+  0,                                  /* tp_as_number */
+  0,                                  /* tp_as_mapping*/
+  0,                                  /* tp_hash      */
+};
+
+/* Create a variable linking object for use later */
+SWIGRUNTIME(PyObject *)
+SWIG_newvarlink(void) {
+  swig_varlinkobject *result = 0;
+  result = PyMem_NEW(swig_varlinkobject,1);
+  varlinktype.ob_type = &PyType_Type;    /* Patch varlinktype into a PyType */
+  result->ob_type = &varlinktype;
+  result->vars = 0;
+  result->ob_refcnt = 0;
+  Py_XINCREF((PyObject *) result);
+  return ((PyObject*) result);
+}
+
+SWIGRUNTIME(void)
+SWIG_addvarlink(PyObject *p, char *name,
+	   PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) {
+  swig_varlinkobject *v;
+  swig_globalvar *gv;
+  v= (swig_varlinkobject *) p;
+  gv = (swig_globalvar *) malloc(sizeof(swig_globalvar));
+  gv->name = (char *) malloc(strlen(name)+1);
+  strcpy(gv->name,name);
+  gv->get_attr = get_attr;
+  gv->set_attr = set_attr;
+  gv->next = v->vars;
+  v->vars = gv;
+}
+/* Convert a pointer value */
+SWIGRUNTIME(int)
+SWIG_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) {
+  unsigned long p;
+  register int d;
+  swig_type_info *tc;
+  char  *c;
+  static PyObject *SWIG_this = 0;
+  int    newref = 0;
+
+  if (!obj || (obj == Py_None)) {
+    *ptr = 0;
+    return 0;
+  }
+#ifdef SWIG_COBJECT_TYPES
+  if (!(PyCObject_Check(obj))) {
+    if (!SWIG_this)
+      SWIG_this = PyString_InternFromString("this");
+    obj = PyObject_GetAttr(obj,SWIG_this);
+    newref = 1;
+    if (!obj) goto type_error;
+    if (!PyCObject_Check(obj)) {
+      Py_DECREF(obj);
+      goto type_error;
+    }
+  } 
+  *ptr = PyCObject_AsVoidPtr(obj);
+  c = (char *) PyCObject_GetDesc(obj);
+  if (newref) Py_DECREF(obj);
+  goto cobject;
+#else
+  if (!(PyString_Check(obj))) {
+    if (!SWIG_this)
+      SWIG_this = PyString_InternFromString("this");
+    obj = PyObject_GetAttr(obj,SWIG_this);
+    newref = 1;
+    if (!obj) goto type_error;
+    if (!PyString_Check(obj)) {
+      Py_DECREF(obj);
+      goto type_error;
+    }
+  } 
+  c = PyString_AsString(obj);
+  p = 0;
+  /* Pointer values must start with leading underscore */
+  if (*c != '_') {
+    *ptr = (void *) 0;
+    if (strcmp(c,"NULL") == 0) {
+      if (newref) Py_DECREF(obj);
+      return 0;
+    } else {
+      if (newref) Py_DECREF(obj);
+      goto type_error;
+    }
+  }
+  c++;
+  /* Extract hex value from pointer */
+  while ((d = *c)) {
+    if ((d >= '0') && (d <= '9'))
+      p = (p << 4) + (d - '0');
+    else if ((d >= 'a') && (d <= 'f'))
+      p = (p << 4) + (d - ('a'-10));
+    else
+      break; 
+    c++;
+  }
+  *ptr = (void *) p;
+  if (newref) Py_DECREF(obj);
+#endif
+
+#ifdef SWIG_COBJECT_TYPES
+cobject:
+#endif
+
+  if (ty) {
+    tc = SWIG_TypeCheck(c,ty);
+    if (!tc) goto type_error;
+    *ptr = SWIG_TypeCast(tc,(void*)p);
+  }
+  return 0;
+
+type_error:
+
+  if (flags) {
+    if (ty) {
+      char *temp = (char *) malloc(64+strlen(ty->name));
+      sprintf(temp,"Type error. Expected %s", ty->name);
+      PyErr_SetString(PyExc_TypeError, temp);
+      free((char *) temp);
+    } else {
+      PyErr_SetString(PyExc_TypeError,"Expected a pointer");
+    }
+  }
+  return -1;
+}
+
+/* Take a pointer and convert it to a string */
+SWIGRUNTIME(void) 
+SWIG_MakePtr(char *c, void *ptr, swig_type_info *ty) {
+  static char hex[17] = "0123456789abcdef";
+  unsigned long p, s;
+  char result[32], *r; 
+  r = result;
+  p = (unsigned long) ptr;
+  if (p > 0) {
+    while (p > 0) {
+      s = p & 0xf;
+      *(r++) = hex[s];
+      p = p >> 4;
+    }
+    *r = '_';
+    while (r >= result)
+      *(c++) = *(r--);
+    strcpy (c, ty->name);
+  } else {
+    strcpy (c, "NULL");
+  }
+}
+
+/* Create a new pointer object */
+SWIGRUNTIME(PyObject *)
+SWIG_NewPointerObj(void *ptr, swig_type_info *type) {
+  char result[512];
+  PyObject *robj;
+  if (!ptr) {
+    Py_INCREF(Py_None);
+    return Py_None;
+  }
+#ifdef SWIG_COBJECT_TYPES
+  robj = PyCObject_FromVoidPtrAndDesc((void *) ptr, type->name, NULL);
+#else
+  SWIG_MakePtr(result,ptr,type);
+  robj = PyString_FromString(result);
+#endif
+  return robj;
+}
+
+/* Install Constants */
+SWIGRUNTIME(void)
+SWIG_InstallConstants(PyObject *d, swig_const_info constants[]) {
+  int i;
+  PyObject *obj;
+  for (i = 0; constants[i].type; i++) {
+    switch(constants[i].type) {
+    case SWIG_PY_INT:
+      obj = PyInt_FromLong(constants[i].lvalue);
+      break;
+    case SWIG_PY_FLOAT:
+      obj = PyFloat_FromDouble(constants[i].dvalue);
+      break;
+    case SWIG_PY_STRING:
+      obj = PyString_FromString((char *) constants[i].pvalue);
+      break;
+    case SWIG_PY_POINTER:
+      obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype);
+      break;
+    default:
+      obj = 0;
+      break;
+    }
+    if (obj) {
+      PyDict_SetItemString(d,constants[i].name,obj);
+      Py_DECREF(obj);
+    }
+  }
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+/* -------- TYPES TABLE (BEGIN) -------- */
+
+#define  SWIGTYPE_p_float swig_types[0] 
+#define  SWIGTYPE_p_double swig_types[1] 
+#define  SWIGTYPE_p_p_char swig_types[2] 
+#define  SWIGTYPE_p_PJ swig_types[3] 
+#define  SWIGTYPE_p_int swig_types[4] 
+#define  SWIGTYPE_p_Projection swig_types[5] 
+static swig_type_info *swig_types[7];
+
+/* -------- TYPES TABLE (END) -------- */
+
+
+/*-----------------------------------------------
+              @(target):= Projectionc.so
+  ------------------------------------------------*/
+#define SWIG_init    initProjectionc
+
+#define SWIG_name    "Projectionc"
+
+#include <projects.h>
+
+    // We wrap the PJ structure in our own so we can keep the
+    // type of units the user wants to operate in along.
+    typedef enum {DEGREES, RADIANS} Units;
+    typedef struct {
+	Units units;
+	PJ *proj;
+    } Projection;
+
+static PyObject* l_output_helper(PyObject* target, PyObject* o) {
+    PyObject*   o2;
+    if (!target) {                   
+        target = o;
+    } else if (target == Py_None) {  
+        Py_DECREF(Py_None);
+        target = o;
+    } else {                         
+        if (!PyList_Check(target)) {
+            o2 = target;
+            target = PyList_New(0);
+            PyList_Append(target, o2);
+	    Py_XDECREF(o2);
+        }
+        PyList_Append(target,o);
+	Py_XDECREF(o);
+    }
+    return target;
+}
+
+static PyObject* t_output_helper(PyObject* target, PyObject* o) {
+    PyObject*   o2;
+    PyObject*   o3;
+
+    if (!target) {                   
+        target = o;
+    } else if (target == Py_None) {  
+        Py_DECREF(Py_None);
+        target = o;
+    } else {                         
+        if (!PyTuple_Check(target)) {
+            o2 = target;
+            target = PyTuple_New(1);
+            PyTuple_SetItem(target, 0, o2);
+        }
+        o3 = PyTuple_New(1);            
+        PyTuple_SetItem(o3, 0, o);      
+
+        o2 = target;
+        target = PySequence_Concat(o2, o3); 
+        Py_DECREF(o2);                      
+        Py_DECREF(o3);
+    }
+    return target;
+}
+
+#define  SWIG_MemoryError    1
+#define  SWIG_IOError        2
+#define  SWIG_RuntimeError   3
+#define  SWIG_IndexError     4
+#define  SWIG_TypeError      5
+#define  SWIG_DivisionByZero 6
+#define  SWIG_OverflowError  7
+#define  SWIG_SyntaxError    8
+#define  SWIG_ValueError     9
+#define  SWIG_SystemError   10
+#define  SWIG_UnknownError  99
+
+static void _SWIG_exception(int code, char *msg) {
+  switch(code) {
+  case SWIG_MemoryError:
+    PyErr_SetString(PyExc_MemoryError,msg);
+    break;
+  case SWIG_IOError:
+    PyErr_SetString(PyExc_IOError,msg);
+    break;
+  case SWIG_RuntimeError:
+    PyErr_SetString(PyExc_RuntimeError,msg);
+    break;
+  case SWIG_IndexError:
+    PyErr_SetString(PyExc_IndexError,msg);
+    break;
+  case SWIG_TypeError:
+    PyErr_SetString(PyExc_TypeError,msg);
+    break;
+  case SWIG_DivisionByZero:
+    PyErr_SetString(PyExc_ZeroDivisionError,msg);
+    break;
+  case SWIG_OverflowError:
+    PyErr_SetString(PyExc_OverflowError,msg);
+    break;
+  case SWIG_SyntaxError:
+    PyErr_SetString(PyExc_SyntaxError,msg);
+    break;
+  case SWIG_ValueError:
+    PyErr_SetString(PyExc_ValueError,msg);
+    break;
+  case SWIG_SystemError:
+    PyErr_SetString(PyExc_SystemError,msg);
+    break;
+  default:
+    PyErr_SetString(PyExc_RuntimeError,msg);
+    break;
+  }
+}
+
+#define SWIG_exception(a,b) { _SWIG_exception(a,b); return NULL; }
+
+#include <limits.h>
+
+/* Create a new integer array */
+
+  static int *int_array(int size) {
+#ifdef __cplusplus
+    return new int[size];
+#else
+    return (int *) malloc(size*sizeof(int));
+#endif
+  }
+
+  /* Destroy an integer array */
+
+  static void int_destroy(int *array) {
+    if (array) {
+#ifdef __cplusplus
+      delete [] array;
+#else
+      free(array);
+#endif
+    }
+  }
+
+  /* Return an element */
+
+  static int int_get(int *array, int index) {
+    if (array) {
+      return array[index];
+    } else {
+      return INT_MIN;
+    }
+  }
+   
+  /* Set an element */
+  
+  static int int_set(int *array, int index, int value) {
+    if (array) {
+      return (array[index] = value);
+    } else {
+      return INT_MIN;
+    }
+  }
+
+
+  #include <float.h>
+
+  /* Create a new float array */
+
+  static float *float_array(int size) {
+#ifdef __cplusplus
+    return new float[size];
+#else
+    return (float *) malloc(size*sizeof(float));
+#endif
+  }
+
+  /* Destroy an array */
+
+  static void float_destroy(float *array) {
+    if (array) {
+#ifdef __cplusplus
+      delete [] array;
+#else
+      free(array);
+#endif
+    }
+  }
+
+  /* Return an element */
+
+  static float float_get(float *array, int index) {
+    if (array) {
+      return array[index];
+    } else {
+      return FLT_MIN;
+    }
+  }
+   
+  /* Set an element */
+  
+  static float float_set(float *array, int index, float value) {
+    if (array) {
+      return (array[index] = value);
+    } else {
+      return FLT_MIN;
+    }
+  }
+
+  /* Create a new double array */
+
+  static double *double_array(int size) {
+#ifdef __cplusplus
+    return new double[size];
+#else
+    return (double *) malloc(size*sizeof(double));
+#endif
+  }
+
+  /* Destroy an array */
+
+  static void double_destroy(double *array) {
+    if (array) {
+#ifdef __cplusplus
+      delete [] array;
+#else
+      free(array);
+#endif
+    }
+  }
+
+  /* Return an element */
+
+  static double double_get(double *array, int index) {
+    if (array) {
+      return array[index];
+    } else {
+      return FLT_MIN;
+    }
+  }
+   
+  /* Set an element */
+  
+  static double double_set(double *array, int index, double value) {
+    if (array) {
+      return (array[index] = value);
+    } else {
+      return FLT_MIN;
+    }
+  }
+
+
+/* Create character string arrays */
+
+static char **string_array(int size) {
+  char **a;
+  int i;
+#ifdef __cplusplus
+  a = new char *[size];
+#else
+  a = (char **) malloc(size*sizeof(char *));
+#endif
+  for (i = 0; i < size; i++)
+    a[i] = 0;
+  return a;
+}
+
+/* Destroy a string array */
+
+static void string_destroy(char **array) {
+  int i = 0;
+  if (array) {
+      while (array[i]) {
+#ifdef __cplusplus
+            delete array[i];
+#else
+            free(array[i]);
+#endif
+            i++;
+      }          	
+#ifdef __cplusplus
+     delete [] array;
+#else
+     free(array);
+#endif
+   }      
+}
+
+/* Get an element */
+
+static char *string_get(char **array_string, int index) {
+  if (array_string) 
+    if (array_string[index]) return (array_string[index]);
+    else return "";
+  else 
+    return "";
+}
+
+/* Set an element */
+
+static char *string_set(char **array_string, int index, char * val) {
+  if (array_string) {
+    if (array_string[index]) {
+#ifdef __cplusplus
+	delete array_string[index];
+#else
+        free(array_string[index]);
+#endif
+    }	
+    if (strlen(val) > 0) {
+#ifdef __cplusplus
+      array_string[index] = new char[strlen(val)+1];
+#else
+      array_string[index] = (char *) malloc(strlen(val)+1);
+#endif
+      strcpy(array_string[index],val);
+      return array_string[index];
+    } else {
+      array_string[index] = 0;
+      return val;
+    }
+  } else return val;
+}
+
+
+    // Make a brand new projection
+    Projection *new_Projection(char **argv, Units units) {
+	int argc = 0;
+	char **p;
+	PJ *proj;
+	Projection *pj = NULL;
+	
+	for(p = argv; p != NULL && *p != NULL; p++) argc++;
+	proj = pj_init(argc, argv);
+	if(proj != NULL) {
+	    pj = (Projection *) malloc(sizeof(Projection));
+	    pj->units = units;
+	    pj->proj = proj;
+	}
+	return pj;
+    }
+
+    // Get rid of a projection
+    void delete_Projection(Projection *self) {
+	if(self != NULL) {
+	    if(self->proj != NULL)
+		pj_free(self->proj);
+	    free(self);  
+	} 
+    }
+
+    // Do a forward (lat/lon --> world) translation
+    void Projection_Forward(Projection *self, double lat, double lon, double *u, double *v) {
+	projUV latlon, result;
+	latlon.u = lat;
+	latlon.v = lon;
+	if(self->units == DEGREES) {
+	    latlon.u *= DEG_TO_RAD;
+	    latlon.v *= DEG_TO_RAD;
+	}
+	result = pj_fwd(latlon, self->proj);
+	*u = result.u;
+	*v = result.v;
+    }
+
+    // Do a reverse (world --> lat/lon) translation
+    void Projection_Inverse(Projection *self, double u, double v, double *lat, double *lon) {
+	projUV world, result;
+	world.u = u;
+	world.v = v;
+	result = pj_inv(world, self->proj);
+	if(self->units == DEGREES) {
+	    result.u *= RAD_TO_DEG;
+	    result.v *= RAD_TO_DEG;
+	}
+	*lat = result.u;
+	*lon = result.v;
+    }
+#ifdef __cplusplus
+extern "C" {
+#endif
+static PyObject *_wrap_int_array(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    int arg0 ;
+    int *result ;
+    
+    if(!PyArg_ParseTuple(args,"i:int_array",&arg0)) return NULL;
+    result = (int *)int_array(arg0);
+    resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_int);
+    {
+        if (!result) {
+            SWIG_exception(SWIG_MemoryError,"Out of memory.");
+        }
+    }
+    return resultobj;
+}
+
+
+static PyObject *_wrap_int_destroy(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    int *arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:int_destroy",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_int,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    int_destroy(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+static PyObject *_wrap_int_get(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    int *arg0 ;
+    int arg1 ;
+    PyObject * argo0 =0 ;
+    int result ;
+    
+    if(!PyArg_ParseTuple(args,"Oi:int_get",&argo0,&arg1)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_int,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    result = (int )int_get(arg0,arg1);
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_int_set(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    int *arg0 ;
+    int arg1 ;
+    int arg2 ;
+    PyObject * argo0 =0 ;
+    int result ;
+    
+    if(!PyArg_ParseTuple(args,"Oii:int_set",&argo0,&arg1,&arg2)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_int,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    result = (int )int_set(arg0,arg1,arg2);
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_double_array(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    int arg0 ;
+    double *result ;
+    
+    if(!PyArg_ParseTuple(args,"i:double_array",&arg0)) return NULL;
+    result = (double *)double_array(arg0);
+    resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_double);
+    {
+        if (!result) {
+            SWIG_exception(SWIG_MemoryError,"Out of memory.");
+        }
+    }
+    return resultobj;
+}
+
+
+static PyObject *_wrap_double_destroy(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    double *arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:double_destroy",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_double,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    double_destroy(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+static PyObject *_wrap_double_get(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    double *arg0 ;
+    int arg1 ;
+    PyObject * argo0 =0 ;
+    double result ;
+    
+    if(!PyArg_ParseTuple(args,"Oi:double_get",&argo0,&arg1)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_double,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    result = (double )double_get(arg0,arg1);
+    resultobj = PyFloat_FromDouble(result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_double_set(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    double *arg0 ;
+    int arg1 ;
+    double arg2 ;
+    PyObject * argo0 =0 ;
+    double result ;
+    
+    if(!PyArg_ParseTuple(args,"Oid:double_set",&argo0,&arg1,&arg2)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_double,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    result = (double )double_set(arg0,arg1,arg2);
+    resultobj = PyFloat_FromDouble(result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_float_array(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    int arg0 ;
+    float *result ;
+    
+    if(!PyArg_ParseTuple(args,"i:float_array",&arg0)) return NULL;
+    result = (float *)float_array(arg0);
+    resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_float);
+    {
+        if (!result) {
+            SWIG_exception(SWIG_MemoryError,"Out of memory.");
+        }
+    }
+    return resultobj;
+}
+
+
+static PyObject *_wrap_float_destroy(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    float *arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:float_destroy",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_float,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    float_destroy(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+static PyObject *_wrap_float_get(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    float *arg0 ;
+    int arg1 ;
+    PyObject * argo0 =0 ;
+    float result ;
+    
+    if(!PyArg_ParseTuple(args,"Oi:float_get",&argo0,&arg1)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_float,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    result = (float )float_get(arg0,arg1);
+    resultobj = PyFloat_FromDouble(result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_float_set(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    float *arg0 ;
+    int arg1 ;
+    float arg2 ;
+    PyObject * argo0 =0 ;
+    float result ;
+    
+    if(!PyArg_ParseTuple(args,"Oif:float_set",&argo0,&arg1,&arg2)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_float,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    result = (float )float_set(arg0,arg1,arg2);
+    resultobj = PyFloat_FromDouble(result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_string_array(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    int arg0 ;
+    char **result ;
+    
+    if(!PyArg_ParseTuple(args,"i:string_array",&arg0)) return NULL;
+    result = (char **)string_array(arg0);
+    resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_p_char);
+    {
+        if (!result) {
+            SWIG_exception(SWIG_MemoryError,"Out of memory.");
+        }
+    }
+    return resultobj;
+}
+
+
+static PyObject *_wrap_string_destroy(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    char **arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:string_destroy",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_p_char,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    string_destroy(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+static PyObject *_wrap_string_get(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    char **arg0 ;
+    int arg1 ;
+    PyObject * argo0 =0 ;
+    char *result ;
+    
+    if(!PyArg_ParseTuple(args,"Oi:string_get",&argo0,&arg1)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_p_char,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    result = (char *)string_get(arg0,arg1);
+    resultobj = PyString_FromString(result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_string_set(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    char **arg0 ;
+    int arg1 ;
+    char *arg2 ;
+    PyObject * argo0 =0 ;
+    char *result ;
+    
+    if(!PyArg_ParseTuple(args,"Ois:string_set",&argo0,&arg1,&arg2)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_p_char,1)) == -1) return NULL;
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    result = (char *)string_set(arg0,arg1,arg2);
+    resultobj = PyString_FromString(result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_Projection_units_set(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    Projection *arg0 ;
+    int arg1 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"Oi:Projection_units_set",&argo0,&arg1)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_Projection,1)) == -1) return NULL;
+    arg0->units = (Units )arg1;
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+static PyObject *_wrap_Projection_units_get(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    Projection *arg0 ;
+    PyObject * argo0 =0 ;
+    int result ;
+    
+    if(!PyArg_ParseTuple(args,"O:Projection_units_get",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_Projection,1)) == -1) return NULL;
+    result = (int ) (arg0->units);
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_Projection_proj_set(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    Projection *arg0 ;
+    PJ *arg1 ;
+    PyObject * argo0 =0 ;
+    PyObject * argo1 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"OO:Projection_proj_set",&argo0,&argo1)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_Projection,1)) == -1) return NULL;
+    if ((SWIG_ConvertPtr(argo1,(void **) &arg1,SWIGTYPE_p_PJ,1)) == -1) return NULL;
+    arg0->proj = arg1;
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+static PyObject *_wrap_Projection_proj_get(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    Projection *arg0 ;
+    PyObject * argo0 =0 ;
+    PJ *result ;
+    
+    if(!PyArg_ParseTuple(args,"O:Projection_proj_get",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_Projection,1)) == -1) return NULL;
+    result = (PJ *) (arg0->proj);
+    resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_PJ);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_new_Projection(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    char **arg0 ;
+    int arg1 = DEGREES ;
+    PyObject * obj0  = 0 ;
+    Projection *result ;
+    
+    if(!PyArg_ParseTuple(args,"O|i:new_Projection",&obj0,&arg1)) return NULL;
+    {
+        /* Check if is a list */ 
+        if (PyList_Check(obj0)) {
+            int size = PyList_Size(obj0); 
+            int i = 0; 
+            arg0 = (char **) malloc((size+1)*sizeof(char *)); 
+            for (i = 0; i < size; i++) {
+                PyObject *o = PyList_GetItem(obj0,i); 
+                if (PyString_Check(o)) 
+                arg0[i] = PyString_AsString(PyList_GetItem(obj0,i)); 
+                else {
+                    PyErr_SetString(PyExc_TypeError,"list must contain strings"); 
+                    free(arg0); 
+                    return NULL; 
+                }
+            }
+            arg0[i] = 0; 
+        }else {
+            PyErr_SetString(PyExc_TypeError,"not a list"); return NULL; 
+        }
+    }
+    {
+        if (!arg0) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    {
+        /* Use pj_get_errno_ref to access the pj_errno because directly
+        * accessing pj_errno doesn't work on windows if the proj library is
+     * in a DLL */
+    *pj_get_errno_ref() = 0;
+    result = (Projection *)new_Projection(arg0,(Units )arg1);
+;
+    if (!result)
+    {
+	/* FIXME: There's a case where result is NULL and pj_errno is
+        * not set, namely when memory allocation of the Projection
+        * struct fails. */
+        SWIG_exception(SWIG_IOError, pj_strerrno(*pj_get_errno_ref()));
+    }
+}resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_Projection);
+{
+    free((char *) arg0);
+}
+return resultobj;
+}
+
+
+static PyObject *_wrap_delete_Projection(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    Projection *arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:delete_Projection",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_Projection,1)) == -1) return NULL;
+    delete_Projection(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+static PyObject *_wrap_Projection_Forward(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    Projection *arg0 ;
+    double arg1 ;
+    double arg2 ;
+    double *arg3 ;
+    double *arg4 ;
+    double temp ;
+    double temp0 ;
+    PyObject * argo0 =0 ;
+    
+    {
+        arg3 = &temp;
+    }
+    {
+        arg4 = &temp0;
+    }
+    if(!PyArg_ParseTuple(args,"Odd:Projection_Forward",&argo0,&arg1,&arg2)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_Projection,1)) == -1) return NULL;
+    {
+        if (!arg3) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    {
+        if (!arg4) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    Projection_Forward(arg0,arg1,arg2,arg3,arg4);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    {
+        PyObject *o; 
+        o = PyFloat_FromDouble(*arg3); 
+        if ((!resultobj) || (resultobj == Py_None)) {
+            resultobj = o; 
+        }else {
+            if (!PyList_Check(resultobj)) {
+                PyObject *o2 = resultobj; 
+                resultobj = PyList_New(0); 
+                PyList_Append(resultobj,o2); 
+                Py_XDECREF(o2); 
+            }
+            PyList_Append(resultobj,o); 
+            Py_XDECREF(o); 
+        }
+    }
+    {
+        PyObject *o; 
+        o = PyFloat_FromDouble(*arg4); 
+        if ((!resultobj) || (resultobj == Py_None)) {
+            resultobj = o; 
+        }else {
+            if (!PyList_Check(resultobj)) {
+                PyObject *o2 = resultobj; 
+                resultobj = PyList_New(0); 
+                PyList_Append(resultobj,o2); 
+                Py_XDECREF(o2); 
+            }
+            PyList_Append(resultobj,o); 
+            Py_XDECREF(o); 
+        }
+    }
+    return resultobj;
+}
+
+
+static PyObject *_wrap_Projection_Inverse(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    Projection *arg0 ;
+    double arg1 ;
+    double arg2 ;
+    double *arg3 ;
+    double *arg4 ;
+    double temp ;
+    double temp0 ;
+    PyObject * argo0 =0 ;
+    
+    {
+        arg3 = &temp;
+    }
+    {
+        arg4 = &temp0;
+    }
+    if(!PyArg_ParseTuple(args,"Odd:Projection_Inverse",&argo0,&arg1,&arg2)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_Projection,1)) == -1) return NULL;
+    {
+        if (!arg3) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    {
+        if (!arg4) {
+            SWIG_exception(SWIG_ValueError,"Received a NULL Pointer");
+        }
+    }
+    Projection_Inverse(arg0,arg1,arg2,arg3,arg4);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    {
+        PyObject *o; 
+        o = PyFloat_FromDouble(*arg3); 
+        if ((!resultobj) || (resultobj == Py_None)) {
+            resultobj = o; 
+        }else {
+            if (!PyList_Check(resultobj)) {
+                PyObject *o2 = resultobj; 
+                resultobj = PyList_New(0); 
+                PyList_Append(resultobj,o2); 
+                Py_XDECREF(o2); 
+            }
+            PyList_Append(resultobj,o); 
+            Py_XDECREF(o); 
+        }
+    }
+    {
+        PyObject *o; 
+        o = PyFloat_FromDouble(*arg4); 
+        if ((!resultobj) || (resultobj == Py_None)) {
+            resultobj = o; 
+        }else {
+            if (!PyList_Check(resultobj)) {
+                PyObject *o2 = resultobj; 
+                resultobj = PyList_New(0); 
+                PyList_Append(resultobj,o2); 
+                Py_XDECREF(o2); 
+            }
+            PyList_Append(resultobj,o); 
+            Py_XDECREF(o); 
+        }
+    }
+    return resultobj;
+}
+
+
+PyObject * Projection_cobject(Projection *self) {
+    {
+        return PyCObject_FromVoidPtr(self->proj, NULL);
+    }
+}
+
+
+static PyObject *_wrap_Projection_cobject(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    Projection *arg0 ;
+    PyObject * argo0 =0 ;
+    PyObject *result ;
+    
+    if(!PyArg_ParseTuple(args,"O:Projection_cobject",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_Projection,1)) == -1) return NULL;
+    result = (PyObject *)Projection_cobject(arg0);
+    {
+        resultobj = result;
+    }
+    return resultobj;
+}
+
+
+static PyMethodDef ProjectioncMethods[] = {
+	 { "int_array", _wrap_int_array, METH_VARARGS },
+	 { "int_destroy", _wrap_int_destroy, METH_VARARGS },
+	 { "int_get", _wrap_int_get, METH_VARARGS },
+	 { "int_set", _wrap_int_set, METH_VARARGS },
+	 { "double_array", _wrap_double_array, METH_VARARGS },
+	 { "double_destroy", _wrap_double_destroy, METH_VARARGS },
+	 { "double_get", _wrap_double_get, METH_VARARGS },
+	 { "double_set", _wrap_double_set, METH_VARARGS },
+	 { "float_array", _wrap_float_array, METH_VARARGS },
+	 { "float_destroy", _wrap_float_destroy, METH_VARARGS },
+	 { "float_get", _wrap_float_get, METH_VARARGS },
+	 { "float_set", _wrap_float_set, METH_VARARGS },
+	 { "string_array", _wrap_string_array, METH_VARARGS },
+	 { "string_destroy", _wrap_string_destroy, METH_VARARGS },
+	 { "string_get", _wrap_string_get, METH_VARARGS },
+	 { "string_set", _wrap_string_set, METH_VARARGS },
+	 { "Projection_units_set", _wrap_Projection_units_set, METH_VARARGS },
+	 { "Projection_units_get", _wrap_Projection_units_get, METH_VARARGS },
+	 { "Projection_proj_set", _wrap_Projection_proj_set, METH_VARARGS },
+	 { "Projection_proj_get", _wrap_Projection_proj_get, METH_VARARGS },
+	 { "new_Projection", _wrap_new_Projection, METH_VARARGS },
+	 { "delete_Projection", _wrap_delete_Projection, METH_VARARGS },
+	 { "Projection_Forward", _wrap_Projection_Forward, METH_VARARGS },
+	 { "Projection_Inverse", _wrap_Projection_Inverse, METH_VARARGS },
+	 { "Projection_cobject", _wrap_Projection_cobject, METH_VARARGS },
+	 { NULL, NULL }
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
+
+static swig_type_info _swigt__p_float[] = {{"_p_float", 0, "float *"},{"_p_float"},{0}};
+static swig_type_info _swigt__p_double[] = {{"_p_double", 0, "double *"},{"_p_double"},{0}};
+static swig_type_info _swigt__p_p_char[] = {{"_p_p_char", 0, "char **"},{"_p_p_char"},{0}};
+static swig_type_info _swigt__p_PJ[] = {{"_p_PJ", 0, "PJ *"},{"_p_PJ"},{0}};
+static swig_type_info _swigt__p_int[] = {{"_p_int", 0, "int *"},{"_p_int"},{0}};
+static swig_type_info _swigt__p_Projection[] = {{"_p_Projection", 0, "Projection *"},{"_p_Projection"},{0}};
+
+static swig_type_info *swig_types_initial[] = {
+_swigt__p_float, 
+_swigt__p_double, 
+_swigt__p_p_char, 
+_swigt__p_PJ, 
+_swigt__p_int, 
+_swigt__p_Projection, 
+0
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
+
+static swig_const_info swig_const_table[] = {
+    { SWIG_PY_INT,     "DEGREES", (long) DEGREES, 0, 0, 0},
+    { SWIG_PY_INT,     "RADIANS", (long) RADIANS, 0, 0, 0},
+{0}};
+
+static PyObject *SWIG_globals;
+#ifdef __cplusplus
+extern "C" 
+#endif
+SWIGEXPORT(void) initProjectionc(void) {
+    PyObject *m, *d;
+    int i;
+    SWIG_globals = SWIG_newvarlink();
+    m = Py_InitModule("Projectionc", ProjectioncMethods);
+    d = PyModule_GetDict(m);
+    for (i = 0; swig_types_initial[i]; i++) {
+        swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);
+    }
+    SWIG_InstallConstants(d,swig_const_table);
+}
+

Added: packages/thuban/branches/upstream/current/libraries/pyprojection/setup.py
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyprojection/setup.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyprojection/setup.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,22 @@
+
+import os, os.path
+from distutils.core import setup, Extension
+
+PROJ4_PREFIX = "/"
+PROJ4_INCLUDE = os.path.join(PROJ4_PREFIX, "usr/local/include")
+PROJ4_LIB = os.path.join(PROJ4_PREFIX, "usr/local/lib")
+
+extensions = [Extension("Projectionc",
+                        ["Projection_wrap.c"],
+                        include_dirs = [PROJ4_INCLUDE],
+                        library_dirs = [PROJ4_LIB],
+                        libraries = ["proj"])]
+
+setup(name = "py-Projection",
+      version = "0.1",
+      description = "Python bindings for PROJ.4",
+      author = "Douglas K. Rand",
+      author_email = "rand at meridian-enviro.com",
+      py_modules = ["Projection"],
+      ext_modules = extensions)
+

Added: packages/thuban/branches/upstream/current/libraries/pyprojection/swighelp.txt
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyprojection/swighelp.txt	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyprojection/swighelp.txt	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,7 @@
+swig1.1 -python -shadow Projection.i
+
+gcc -fpic -c Projection_wrap.c -I/usr/local/include/python1.5 -I/home/Agena/jeinhorn/project/proj4-pythonbindings/src
+
+
+gcc -shared Projection_wrap.o -o Projectionmodule.so -L/usr/local/lib -lproj
+

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/COPYING
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/COPYING	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/COPYING	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,481 @@
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+    		    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/ChangeLog
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/ChangeLog	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/ChangeLog	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,207 @@
+2006-09-24  Bernhard Reiter  <bernhard at intevation.de>
+
+	* dbflib_wrap.c, README: Checked for python version >= 2.4.0a0
+	before using &PyOS_ascii_atof.
+
+2006-09-24  Bernhard Reiter  <bernhard at intevation.de>
+
+	Added dirty workaround to make dbflib agnostic 
+	against decimal_poinst != ".\0".
+
+	* dbflib_wrap.c: Added call DBFSetatof_function(&PyOS_ascii_atof);
+	to initdbflibc(). 
+	* README: noted that manual editing of dbflib_wrap.c is necessary now.
+
+2005-06-30  Bernhard Herzog  <bh at intevation.de>
+
+	* shapelib.i (new_SHPObject): Fix the test for the length of the
+	part types.  It used the wrong variable.
+
+	* shapelib_wrap.c: Regenerated from shapelib.i
+
+	* pytest.py (make_shapefile): Add some more comments and add an
+	example with a polygon with a hole.
+
+2004-12-27  Bernhard Reiter  <bernhard at intevation.de>
+	
+	* README: Refering to the new homepage shapelib.maptools.org now.
+
+2004-12-13  Bernhard Herzog  <bh at intevation.de>
+
+	* dbflib.py: Updated from difflib.i with SWIG.
+
+	* dbflib.i: Work around a bug in the generated python code which
+	leads to exception in the __del__ method when the constructor
+	fails.  See the comments in the code for more details.
+
+2004-05-28  Bernhard Herzog  <bh at intevation.de>
+
+	* README: Flesh out the some more.  Correct the shapelib
+	requirements.
+
+	* NEWS: Update the date of the actual release of 0.3
+
+2004-05-28  Bernhard Herzog  <bh at intevation.de>
+
+	* setup.py: Determine shp_dir correctly when run with bdist_rpm
+	(dbf_macros): Remove a debug print
+
+	* NEWS: Also mention the new (compared to 0.2) setup.py
+
+	* MANIFEST.in: New. Define which files belong into a source
+	distribution
+
+2004-05-17  Bernhard Herzog  <bh at intevation.de>
+
+	* README: Update for new release
+
+	* setup.py (dbf_macros): New. Return the preprocessor macros
+	needed to compile the dbflib wrapper.  Determine whether
+	DBFUpdateHeader is available and define the right value of
+	HAVE_UPDATE_HEADER
+	(extensions): Use dbf_macros for the dbflibc extension
+
+	* dbflib_wrap.c, dbflib.py: Update from dbflib.i
+
+	* dbflib.i (DBFInfo_commit): New. Implementation of the commit
+	method.  This new indirection is necessary because we use the
+	DBFUpdateHeader function now which is not available in shapelib <=
+	1.2.10
+	(DBFFile::commit): Use DBFInfo_commit as implementation
+	(pragma __class__): New. Kludge to remove the commit method when
+	the DBFUpdateHeader function isn't available
+	(_have_commit): New. Helper for the pragma kludge.
+
+2003-11-03  Bernhard Herzog  <bh at intevation.de>
+
+	* dbflib.i (do_read_attribute): New helper function for reading
+	one attribute as a python object
+	(DBFInfo_read_attribute): New. Implement the read_attribute method
+	(DBFInfo_read_record): Use do_read_attribute to read the
+	individual values
+	(struct DBFFile): Add the read_attribute method.
+
+	* dbflib_wrap.c, dbflib.py: Update from dbflib.i.
+
+2003-09-29  Bernhard Herzog  <bh at intevation.de>
+
+	* dbflib.i: Add exception typemap for the add_field method. Fixes
+	Thuban bug RT#1842
+
+	* dbflib_wrap.c: Update from dbflib.i
+
+	* testdbf.py: New. Test cases for the dbflib bindings based on the
+	unittest module
+
+2003-08-18  Bernhard Herzog  <bh at intevation.de>
+
+	* dbflib.i (DBFInfo_write_record): Use PySequence_Check instead of
+	PyMapping_Check to distinguish between sequences and mappings
+	because in Python 2.3, PyMapping_Check returns true for tuples and
+	lists too.
+
+2003-05-28  Bernhard Herzog  <bh at intevation.de>
+
+	* dbflib.i (DBFInfo_read_record): Read NULL fields as None unless
+	it's a string field. DBF files can't distinguish between NULL and
+	an empty string. Also, check the return value of
+	DBFReadStringAttribute which may return NULL to indicate errors.
+
+	* dbflib_wrap.c: Updated from dbflib.i
+
+2002-08-27  Bernhard Herzog  <bh at intevation.de>
+
+	* dbflib.i: Raise an exception if open or create fails.
+
+	* shapelib.i: Slightly better wording for the IOError exception
+	that open and create may raise.
+
+	* shapelib_wrap.c, dbflib_wrap.c: Regenerated
+
+2002-08-22  Bernhard Herzog  <bh at intevation.de>
+
+	* dbflib.i (DBFFile::commit): New method for DBFCommit.
+
+	* dbflib_wrap.c, dbflib.py: Update from dbflib.i
+
+2002-08-15  Bernhard Herzog  <bh at intevation.de>
+
+	* shapelib.i, dbflib.i: Make the NOCHECK trick for the ShapeFile *
+	check typemap work with SWIG 1.3.
+
+	* shapelib_wrap.c, dbflib_wrap.c: Regenerate from the .i files.
+
+2002-05-10  Bernhard Herzog  <bh at intevation.de>
+
+	* dbflib.i (DBFInfo_write_record): Only DECREF if the return value
+	of PyMapping_GetItemString is not NULL. Also, test the return
+	value of PySequence_GetItem
+	(write_field): Remove some debug prints
+
+	* dbflib_wrap.c: Updated from dbflib.i
+
+2002-05-07  Bernhard Herzog  <bh at intevation.de>
+
+	* shptreemodule.c (SHPTreeType, initshptree): Set SHPTreeType's
+	PyType_Type pointer in the init function.
+	(shptree_methods): Use METH_VARARGS
+	(shptree_dealloc): Use PyMem_DEL
+	(shptree_find_shapes): Add a missing return
+
+2002-05-07  Bernhard Herzog  <bh at intevation.de>
+
+	* shptreemodule.c: New file with a simple wrapper for shapelib's
+	quadtree
+
+	* setup.py: Some fixes to use explicit forward slashes as
+	directory separators because of distutils.
+	(extensions): Add the shptree module.
+
+	* pytest.py (read_shapefile): Add some demo calls for the shptree
+	module
+
+	* pyshapelib_api.h (PyShapeLibAPI): Add some of the shptree
+	functions.
+	(PYSHAPELIB_IMPORT_API): New macro to import the API
+
+	* shapelib.i (the_api): add the tree API functions.
+
+	* shapelib_wrap.c: Updated from shapelib.i with SWIG.
+
+2002-04-11  Bernhard Herzog  <bh at intevation.de>
+
+	* pyshapelib_api.h: New file with a limited C-level API for
+	accessing shapilib functions from other Python-extensions.
+
+	* shapelib.i: Export the C-level API with the c_api function.
+
+	* shapelib.py, shapelib_wrap.c: Updated from shapelib.i. Still
+	done with a very old version of SWIG, but it's probably not worth
+	it to try it with a newer version as long as this still works.
+
+2001-07-18  Bernhard Herzog  <bh at intevation.de>
+
+	* shapelib.i (open_ShapeFile): declare the swig prototype
+	correctly with ShapeFile* as return type
+	(ShapeFile.cobject): New method returning the SHPHandle* as a
+	CObject
+
+	* Makefile (VERSION): Increase to 0.3
+
+	* setup.py, MANIFEST.in: New files for python distutils. 
+
+2001-06-15  Bernhard Herzog  <bh at intevation.de>
+
+	* Makefile (VERSION): Increase to 0.2
+
+2001-06-14  Bernhard Herzog  <bh at intevation.de>
+
+	* shapelib.i: Add the functions SHPTypeName as type_name and
+	SHPPartTypeName as part_type_name
+	(SHPObject_vertices):
+	(build_vertex_list): Put building a list of vertices into the
+	separate function build_vertex_list so that SHPObject_vertices can
+	support SHPT_POINT too.
+
+	* ChangeLog: create ChangeLog
+

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/MANIFEST.in
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/MANIFEST.in	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/MANIFEST.in	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,8 @@
+include README COPYING ChangeLog NEWS
+include *.i *.c *.py *.h
+include MANIFEST.in 
+
+# prune the references to the shapelib files which are in either .. or
+# ../shapelib.  These are pulled in by distutils because they're
+# referenced by the Extension objects 
+prune ..

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/NEWS
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/NEWS	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/NEWS	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,43 @@
+pyshapelib 0.3 (2004-05-28)
+===========================
+
+ * New module shptree.  It's a simple wrapper for shapelib's quadtree.
+
+ * Provide a way to access the shapelib module and shapefile objects
+   from C.  It's not documented, unfortunately, but pyshapelib_api.h may
+   be a starting point.  This feature is used in Thuban which could be
+   used as an example.
+
+ * distutils based build and install script, setup.py
+
+Module dbflib:
+
+ * dbf objects now have a method commit if compiled with shapelib newer
+   than 1.2.10 (that is only the CVS version of shapelib at the time of
+   writing).  This method calls the new function dbflib DBFUpdateHeader.
+
+ * New method read_attribute which reads a single attribute instead of a
+   whole record like read_record
+
+ * NULL values are now returned as None.  DBF files don't really support
+   NULL, but this change matches a new feature in shapelib 1.2.9.  It's
+   not clear whether it should be implemented in the python wrapper in
+   this way.  It might be better to make it optional.
+
+
+pyshapelib 0.2 (2001-06-15)
+===========================
+
+Module shapelib:
+
+ * new module level functions type_name and part_type_name
+   (corresponding to SHPTypeName and SHPPartTypeName)
+
+ * The vertices() method of shape objects works for shape type
+   SHPT_POINT, too.
+
+
+pyshapelib 0.1 (2000-12-20)
+===========================
+
+Initial public release

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/README
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,105 @@
+
+Python bindings for Shapelib
+============================
+
+These are three python modules for shapelib:
+
+   shapelib	read/write shapefiles
+
+   dbflib	read/write dbf files
+
+   shptree	quadtree for shapes
+
+Shapelib is a free software library for reading and writing ESRI shape
+files and can be found at http://shapelib.maptools.org/.
+
+The bindings were partly created with SWIG, a tool that can generate
+wrappers of C and C++ libraries for a variety of scripting languages.
+It's homepage is http://www.swig.org.
+
+The bindings themselves don't have a homepage at the moment, but the
+source tarballs/zip files can be downloaded from
+http://ftp.intevation.de/users/bh/pyshapelib/
+
+
+Requirements
+------------
+
+To compile the bindings, you need shapelib 1.2.9 or newer and Python 2.0
+or newer.
+
+SWIG is not required. The files generated by SWIG are contained in the
+archive. If you modify shapelib.i or dbflib.i and need to recreate the
+generated files, you need SWIG 1.3 Alpha 5.  It's unlikely that other
+versions will work.
+In addition you need to add the following lines to  initdbflibc(void)
+in dbflib_wrap.c.
+    /* because we are in a python module now, we can give out
+     * pointers to python's locale agonistic function 
+     * XXX this clearly is a hack
+     */
+    DBFSetatof_function(&PyOS_ascii_atof);
+
+You also need Python, of course.  If you installed prebuilt packages
+such as RPMs of some Linux distributions, please make sure that the
+development package is also installed.
+
+
+License
+-------
+
+The shapelib python bindings are covered by the LGPL. See COPYING for
+more information.
+
+
+Compilation and Installation
+----------------------------
+
+Pyshapelib uses the python distutils which come with Python 2.0 or newer
+and are also available separately from python.org for older versions.
+
+To compile the bindings, unpack the archive under the shapelib archive
+or move the directory there if you've already unpacked it.  The setup
+script expects to find the shapelib files in the parent directory.  Then
+run
+
+    python setup.py build
+
+to build the bindings. The result can be found under the (new) build
+subirectory.
+
+To install run
+
+    python setup.py install
+
+which will install the bindings into python's site-packages directory.
+You can use the intall command's --prefix option to select a different
+installatin directory. 
+
+For more information about the setup.py script, invoke it with the
+--help option:
+
+    python setup.py --help
+
+
+Documentation
+-------------
+
+There's no real documentation for the python bindings themselves, but
+there's a simple demo/test script called pytest.py.
+
+The change history is recorded in NEWS and in detail in ChangeLog.
+
+
+Contact Information
+-------------------
+
+pyshapelib is currently being developed as part of the interactive
+viewer for geographic data Thuban, so the best way to reach the
+developers is to post on the Thuban mailing lists.
+
+Thuban:
+   http://thuban.intevation.org/
+
+Thuban mailing lists:
+   http://thuban.intevation.org/mailinglist.html

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib.i
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib.i	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib.i	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,597 @@
+/* SWIG (www.swig.org) interface file for the dbf interface of shapelib
+ *
+ * At the moment (Dec 2000) this file is only useful to generate Python
+ * bindings. Invoke swig as follows:
+ *
+ *	swig -python -shadow dbflib.i
+ *
+ * to generate dbflib_wrap.c and dbflib.py. dbflib_wrap.c defines a
+ * bunch of Python-functions that wrap the appripriate dbflib functions
+ * and dbflib.py contains an object oriented wrapper around
+ * dbflib_wrap.c.
+ *
+ * This module defines one object type: DBFFile.
+ */
+
+/* this is the dbflib module */
+%module dbflib
+
+/* first a %{,%} block. These blocks are copied verbatim to the
+ * dbflib_wrap.c file and are not parsed by SWIG. This is the place to
+ * import headerfiles and define helper-functions that are needed by the
+ * automatically generated wrappers.
+ */
+
+%{
+#include "shapefil.h"
+
+
+/* Read one attribute from the dbf handle and return it as a new python object
+ *
+ * If an error occurs, set the appropriate Python exception and return
+ * NULL.
+ *
+ * Assume that the values of the record and field arguments are valid.
+ * The name argument will be passed to DBFGetFieldInfo as is and should
+ * thus be either NULL or a pointer to an array of at least 12 chars
+ */
+static PyObject *
+do_read_attribute(DBFInfo * handle, int record, int field, char * name)
+{
+    int type, width;
+    PyObject *value;
+
+    type = DBFGetFieldInfo(handle, field, name, &width, NULL);
+    /* For strings NULL and the empty string are indistinguishable
+     * in DBF files. We prefer empty strings instead for backwards
+     * compatibility reasons because older wrapper versions returned
+     * emtpy strings as empty strings.
+     */
+    if (type != FTString && DBFIsAttributeNULL(handle, record, field))
+    {
+	value = Py_None;
+	Py_INCREF(value);
+    }
+    else
+    {
+	switch (type)
+	{
+	case FTString:
+	{
+	    const char * temp = DBFReadStringAttribute(handle, record, field);
+	    if (temp)
+	    {
+		value = PyString_FromString(temp);
+	    }
+	    else
+	    {
+		PyErr_Format(PyExc_IOError,
+			     "Can't read value for row %d column %d",
+			     record, field);
+		value = NULL;
+	    }
+	    break;
+	}
+	case FTInteger:
+	    value = PyInt_FromLong(DBFReadIntegerAttribute(handle, record,
+							   field));
+	    break;
+	case FTDouble:
+	    value = PyFloat_FromDouble(DBFReadDoubleAttribute(handle, record,
+							      field));
+	    break;
+	default:
+	    PyErr_Format(PyExc_TypeError, "Invalid field data type %d",
+			 type);
+	    value = NULL;
+	}
+    }
+    if (!value)
+	return NULL;
+
+    return value;
+}    
+
+/* the read_attribute method. Return the value of the given record and
+ * field as a python object of the appropriate type.
+ * 
+ * In case of error, set a python exception and return NULL. Since that
+ * value will be returned to the python interpreter as is, the
+ * interpreter should recognize the exception.
+ */
+
+static PyObject *
+DBFInfo_read_attribute(DBFInfo * handle, int record, int field)
+{
+    if (record < 0 || record >= DBFGetRecordCount(handle))
+    {
+	PyErr_Format(PyExc_ValueError,
+		     "record index %d out of bounds (record count: %d)",
+		     record, DBFGetRecordCount(handle));
+	return NULL;
+    }
+
+    if (field < 0 || field >= DBFGetFieldCount(handle))
+    {
+	PyErr_Format(PyExc_ValueError,
+		     "field index %d out of bounds (field count: %d)",
+		     field, DBFGetFieldCount(handle));
+	return NULL;
+    }
+
+    return do_read_attribute(handle, record, field, NULL);
+}
+    
+
+/* the read_record method. Return the record record as a dictionary with
+ * whose keys are the names of the fields, and their values as the
+ * appropriate Python type.
+ * 
+ * In case of error, set a python exception and return NULL. Since that
+ * value will be returned to the python interpreter as is, the
+ * interpreter should recognize the exception.
+ */
+
+static PyObject *
+DBFInfo_read_record(DBFInfo * handle, int record)
+{
+    int num_fields;
+    int i;
+    int type, width;
+    char name[12];
+    PyObject *dict;
+    PyObject *value;
+
+    if (record < 0 || record >= DBFGetRecordCount(handle))
+    {
+	PyErr_Format(PyExc_ValueError,
+		     "record index %d out of bounds (record count: %d)",
+		     record, DBFGetRecordCount(handle));
+	return NULL;
+    }
+
+    dict = PyDict_New();
+    if (!dict)
+	return NULL;
+	
+    num_fields = DBFGetFieldCount(handle);
+    for (i = 0; i < num_fields; i++)
+    {
+	value = do_read_attribute(handle, record, i, name);
+	if (!value)
+	    goto fail;
+
+	PyDict_SetItemString(dict, name, value);
+	Py_DECREF(value);
+    }
+
+    return dict;
+
+ fail:
+    Py_XDECREF(dict);
+    return NULL;
+}
+
+/* the write_record method. Write the record record given wither as a
+ * dictionary or a sequence (i.e. a list or a tuple).
+ *
+ * If it's a dictionary the keys must be the names of the fields and
+ * their value must have a suitable type. Only the fields actually
+ * contained in the dictionary are written. Fields for which there's no
+ * item in the dict are not modified.
+ *
+ * If it's a sequence, all fields must be present in the right order.
+ *
+ * In case of error, set a python exception and return NULL. Since that
+ * value will be returned to the python interpreter as is, the
+ * interpreter should recognize the exception.
+ *
+ * The method is implemented with two c-functions, write_field to write
+ * a single field and DBFInfo_write_record as the front-end.
+ */
+
+
+/* write a single field of a record. */
+static int
+write_field(DBFHandle handle, int record, int field, int type,
+	    PyObject * value)
+{
+    char * string_value;
+    int int_value;
+    double double_value;
+
+    if (value == Py_None)
+    {
+	if (!DBFWriteNULLAttribute(handle, record, field))
+	{
+	    PyErr_Format(PyExc_IOError,
+			 "can't write NULL field %d of record %d",
+			 field, record);
+	    return 0;
+	}
+    }
+    else
+    {
+	switch (type)
+	{
+	case FTString:
+	    string_value = PyString_AsString(value);
+	    if (!string_value)
+		return 0;
+	    if (!DBFWriteStringAttribute(handle, record, field, string_value))
+	    {
+		PyErr_Format(PyExc_IOError,
+			     "can't write field %d of record %d",
+			     field, record);
+		return 0;
+	    }
+	    break;
+
+	case FTInteger:
+	    int_value = PyInt_AsLong(value);
+	    if (int_value == -1 && PyErr_Occurred())
+		return 0;
+	    if (!DBFWriteIntegerAttribute(handle, record, field, int_value))
+	    {
+		PyErr_Format(PyExc_IOError,
+			     "can't write field %d of record %d",
+			     field, record);
+		return 0;
+	    }
+	    break;
+
+	case FTDouble:
+	    double_value = PyFloat_AsDouble(value);
+	    if (double_value == -1 && PyErr_Occurred())
+		return 0;
+	    if (!DBFWriteDoubleAttribute(handle, record, field, double_value))
+	    {
+		PyErr_Format(PyExc_IOError,
+			     "can't write field %d of record %d",
+			     field, record);
+		return 0;
+	    }
+	    break;
+
+	default:
+	    PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);
+	    return 0;
+	}
+    }
+
+    return 1;
+}
+
+static
+PyObject *
+DBFInfo_write_record(DBFHandle handle, int record, PyObject *record_object)
+{
+    int num_fields;
+    int i, length;
+    int type, width;
+    char name[12];
+    PyObject * value = NULL;
+
+    num_fields = DBFGetFieldCount(handle);
+
+    /* We used to use PyMapping_Check to test whether record_object is a
+     * dictionary like object instead of PySequence_Check to test
+     * whether it's a sequence. Unfortunately in Python 2.3
+     * PyMapping_Check returns true for lists and tuples too so the old
+     * approach doesn't work anymore.
+     */
+    if (PySequence_Check(record_object))
+    {
+	/* It's a sequence object. Iterate through all items in the
+	 * sequence and write them to the appropriate field.
+	 */
+	length = PySequence_Length(record_object);
+	if (length != num_fields)
+	{
+	    PyErr_SetString(PyExc_TypeError,
+			    "record must have one item for each field");
+	    goto fail;
+	}
+	for (i = 0; i < length; i++)
+	{
+	    type = DBFGetFieldInfo(handle, i, name, &width, NULL); 
+	    value = PySequence_GetItem(record_object, i);
+	    if (value)
+	    {
+		if (!write_field(handle, record, i, type, value))
+		    goto fail;
+		Py_DECREF(value);
+	    }
+	    else
+	    {
+		goto fail;
+	    }
+	}
+    }
+    else
+    {
+	/* It's a dictionary-like object. Iterate over the names of the
+         * known fields and write the corresponding item
+	 */
+	for (i = 0; i < num_fields; i++)
+	{
+	    type = DBFGetFieldInfo(handle, i, name, &width, NULL);
+
+	    /* if the dictionary has the key name write that object to
+	     * the appropriate field, other wise just clear the python
+	     * exception and do nothing.
+	     */
+	    value = PyMapping_GetItemString(record_object, name);
+	    if (value)
+	    {
+		if (!write_field(handle, record, i, type, value))
+		    goto fail;
+		Py_DECREF(value);
+	    }
+	    else
+	    {
+		PyErr_Clear();
+	    }
+	}
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+
+ fail:
+    Py_XDECREF(value);
+    return NULL;
+}
+%}
+
+
+/* The commit method implementation
+ *
+ * The method relies on the DBFUpdateHeader method which is not
+ * available in shapelib <= 1.2.10.  setup.py defines
+ * HAVE_UPDATE_HEADER's value depending on whether the function is
+ * available in the shapelib version the code is compiled with.
+ */
+%{
+static
+void
+DBFInfo_commit(DBFHandle handle)
+{
+#if HAVE_UPDATE_HEADER
+    DBFUpdateHeader(handle);
+#endif
+}
+%} 
+
+
+/*
+ * The SWIG Interface definition.
+ */
+
+/* include some common SWIG type definitions and standard exception
+   handling code */
+%include typemaps.i
+%include exception.i
+
+/* As for ShapeFile in shapelib.i, We define a new C-struct that holds
+ * the DBFHandle. This is mainly done so we can separate the close()
+ * method from the destructor but it also helps with exception handling.
+ *
+ * After the DBFFile has been opened or created the handle is not NULL.
+ * The close() method closes the file and sets handle to NULL as an
+ * indicator that the file has been closed.
+ */
+
+%{
+    typedef struct {
+	DBFHandle handle;
+    } DBFFile;
+%}
+
+
+/* The first argument to the DBFFile methods is a DBFFile pointer.
+ * We have to check whether handle is not NULL in most methods but not
+ * all. In the destructor and the close method, it's OK for handle to be
+ * NULL. We achieve this by checking whether the preprocessor macro
+ * NOCHECK_$name is defined. SWIG replaces $name with the name of the
+ * function for which the code is inserted. In the %{,%}-block below we
+ * define the macros for the destructor and the close() method.
+ */
+
+%typemap(python,check) DBFFile *{
+%#ifndef NOCHECK_$name
+    if (!$target || !$target->handle)
+	SWIG_exception(SWIG_TypeError, "dbffile already closed");
+%#endif
+}
+
+%{
+#define NOCHECK_delete_DBFFile
+#define NOCHECK_DBFFile_close
+%}
+
+
+/* An exception handle for the constructor and the module level open()
+ * and create() functions.
+ *
+ * Annoyingly, we *have* to put braces around the SWIG_exception()
+ * calls, at least in the python case, because of the way the macro is
+ * written. Of course, always putting braces around the branches of an
+ * if-statement is often considered good practice.
+ */
+%typemap(python,except) DBFFile * {
+    $function;
+    if (!$source)
+    {
+    	SWIG_exception(SWIG_MemoryError, "no memory");
+    }
+    else if (!$source->handle)
+    {
+	SWIG_exception(SWIG_IOError, "$name failed");
+    }
+}
+
+/* Exception handler for the add_field method */
+%typemap(python,except) int DBFFile_add_field {
+    $function;
+    if ($source < 0)
+    {
+    	SWIG_exception(SWIG_RuntimeError, "add_field failed");
+    }
+}
+
+/* define and use some typemaps for the field_info() method whose
+ * C-implementation has three output parameters that are returned
+ * through pointers passed into the function. SWIG already has
+ * definitions for common types such as int* and we can use those for
+ * the last two parameters:
+ */
+
+%apply int * OUTPUT { int * output_width }
+%apply int * OUTPUT { int * output_decimals }
+
+/* the fieldname has to be defined manually: */
+%typemap(python,ignore) char *fieldname_out(char temp[12]) {
+    $target = temp;
+}
+
+%typemap(python,argout) char *fieldname_out() {
+    PyObject * string = PyString_FromString($source);
+    $target = t_output_helper($target,string);
+}
+
+
+
+/*
+ * The SWIG-version of the DBFFile struct 
+ */
+
+typedef	struct
+{
+    %addmethods {
+	DBFFile(const char *file, const char * mode = "rb") {
+	    DBFFile * self = malloc(sizeof(DBFFile));
+	    if (self)
+		self->handle = DBFOpen(file, mode);
+	    return self;
+	}
+	    
+	~DBFFile() {
+	    if (self->handle)
+		DBFClose(self->handle);
+	    free(self);
+	}
+
+	void close() {
+	    if (self->handle)
+		DBFClose(self->handle);
+	    self->handle = NULL;
+	}
+
+	int field_count() {
+	    return DBFGetFieldCount(self->handle);
+	}
+
+	int record_count() {
+	    return DBFGetRecordCount(self->handle);
+	}
+
+	int field_info(int iField, char * fieldname_out,
+		       int * output_width, int * output_decimals) {
+	    return DBFGetFieldInfo(self->handle, iField, fieldname_out,
+				   output_width, output_decimals);
+	}
+	    
+	PyObject * read_record(int record) {
+	    return DBFInfo_read_record(self->handle, record);
+	}
+
+	PyObject * read_attribute(int record, int field) {
+	    return DBFInfo_read_attribute(self->handle, record, field);
+	}
+
+	int add_field(const char * pszFieldName, DBFFieldType eType,
+		      int nWidth, int nDecimals) {
+	    return DBFAddField(self->handle, pszFieldName, eType, nWidth,
+			       nDecimals);
+	}
+
+	PyObject *write_record(int record, PyObject *dict_or_sequence) {
+	    return DBFInfo_write_record(self->handle, record,
+					dict_or_sequence);
+	}
+
+	void commit() {
+	    DBFInfo_commit(self->handle);
+	}
+	/* Delete the commit method from the class if it doesn't have a
+	 * real implementation.
+	 */
+	%pragma(python) addtomethod="__class__:if not dbflibc._have_commit: del commit"
+
+	/* The __del__ method generated by the old SWIG version we're
+	 * tries to access self.thisown which may not be set at all when
+	 * there was an exception during construction.  Therefore we
+	 * override it with our own version.
+	 * FIXME: It would be better to upgrade to a newer SWIG version
+	 * or to get rid of SWIG entirely.
+	 */
+	%pragma(python) addtoclass = "
+    def __del__(self,dbflibc=dbflibc):
+        if getattr(self, 'thisown', 0):
+            dbflibc.delete_DBFFile(self)
+    "
+
+
+    }
+} DBFFile;
+
+
+/*
+ * Two module level functions, open() and create() that correspond to
+ * DBFOpen and DBFCreate respectively. open() is equivalent to the
+ * DBFFile constructor.
+ */
+
+
+%{
+    DBFFile * open_DBFFile(const char * file, const char * mode)
+    {
+	DBFFile * self = malloc(sizeof(DBFFile));
+	if (self)
+	    self->handle = DBFOpen(file, mode);
+	return self;
+    }
+%}
+
+%name(open) %new DBFFile * open_DBFFile(const char * file,
+					const char * mode = "rb");
+
+%{
+    DBFFile * create_DBFFile(const char * file)
+    {
+	DBFFile * self = malloc(sizeof(DBFFile));
+	if (self)
+	    self->handle = DBFCreate(file);
+	return self;
+    }
+%}
+%name(create) %new DBFFile * create_DBFFile(const char * file);
+
+
+
+/* constant definitions copied from shapefil.h */
+typedef enum {
+  FTString,
+  FTInteger,
+  FTDouble,
+  FTInvalid
+} DBFFieldType;
+
+
+/* Put the value of the HAVE_UPDATE_HEADER preprocessor macro into the
+ * wrapper so that the __class__ pragma above knows when to remove the
+ * commit method
+ */
+const int _have_commit = HAVE_UPDATE_HEADER;
+

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib.py
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,76 @@
+# This file was created automatically by SWIG.
+import dbflibc
+class DBFFile:
+    def __init__(self,*args):
+        self.this = apply(dbflibc.new_DBFFile,args)
+        self.thisown = 1
+
+    def __del__(self,dbflibc=dbflibc):
+        if self.thisown == 1 :
+            dbflibc.delete_DBFFile(self)
+    def close(*args):
+        val = apply(dbflibc.DBFFile_close,args)
+        return val
+    def field_count(*args):
+        val = apply(dbflibc.DBFFile_field_count,args)
+        return val
+    def record_count(*args):
+        val = apply(dbflibc.DBFFile_record_count,args)
+        return val
+    def field_info(*args):
+        val = apply(dbflibc.DBFFile_field_info,args)
+        return val
+    def read_record(*args):
+        val = apply(dbflibc.DBFFile_read_record,args)
+        return val
+    def read_attribute(*args):
+        val = apply(dbflibc.DBFFile_read_attribute,args)
+        return val
+    def add_field(*args):
+        val = apply(dbflibc.DBFFile_add_field,args)
+        return val
+    def write_record(*args):
+        val = apply(dbflibc.DBFFile_write_record,args)
+        return val
+    def commit(*args):
+        val = apply(dbflibc.DBFFile_commit,args)
+        return val
+    def __repr__(self):
+        return "<C DBFFile instance at %s>" % (self.this,)
+    if not dbflibc._have_commit: del commit
+    
+    def __del__(self,dbflibc=dbflibc):
+        if getattr(self, 'thisown', 0):
+            dbflibc.delete_DBFFile(self)
+    
+class DBFFilePtr(DBFFile):
+    def __init__(self,this):
+        self.this = this
+        self.thisown = 0
+        self.__class__ = DBFFile
+
+
+
+
+
+#-------------- FUNCTION WRAPPERS ------------------
+
+def open(*args, **kwargs):
+    val = apply(dbflibc.open,args,kwargs)
+    if val: val = DBFFilePtr(val); val.thisown = 1
+    return val
+
+def create(*args, **kwargs):
+    val = apply(dbflibc.create,args,kwargs)
+    if val: val = DBFFilePtr(val); val.thisown = 1
+    return val
+
+
+
+#-------------- VARIABLE WRAPPERS ------------------
+
+FTString = dbflibc.FTString
+FTInteger = dbflibc.FTInteger
+FTDouble = dbflibc.FTDouble
+FTInvalid = dbflibc.FTInvalid
+_have_commit = dbflibc._have_commit

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib_wrap.c
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib_wrap.c	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/dbflib_wrap.c	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1431 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3u-20020503-1857 (Alpha 5)
+ * And later MANUALLY edited at the end.
+ * 
+ * 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
+ * changes to this file unless you know what you are doing--modify the SWIG 
+ * interface file instead. 
+ * ----------------------------------------------------------------------------- */
+
+#define SWIGPYTHON
+/***********************************************************************
+ * common.swg
+ *
+ *     This file contains generic SWIG runtime support for pointer
+ *     type checking as well as a few commonly used macros to control
+ *     external linkage.
+ *
+ * Author : David Beazley (beazley at cs.uchicago.edu)
+ *
+ * Copyright (c) 1999-2000, The University of Chicago
+ * 
+ * This file may be freely redistributed without license or fee provided
+ * this copyright message remains intact.
+ ************************************************************************/
+
+#include <string.h>
+
+#if defined(_WIN32) || defined(__WIN32__)
+#       if defined(_MSC_VER)
+#               if defined(STATIC_LINKED)
+#                       define SWIGEXPORT(a) a
+#               else
+#                       define SWIGEXPORT(a) __declspec(dllexport) a
+#               endif
+#       else
+#               if defined(__BORLANDC__)
+#                       define SWIGEXPORT(a) a _export
+#               else
+#                       define SWIGEXPORT(a) a
+#       endif
+#endif
+#else
+#       define SWIGEXPORT(a) a
+#endif
+
+#ifdef SWIG_GLOBAL
+#define SWIGRUNTIME(a) SWIGEXPORT(a)
+#else
+#define SWIGRUNTIME(a) static a
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct swig_type_info {
+  char  *name;                 
+  void *(*converter)(void *);
+  char  *str;
+  struct swig_type_info  *next;
+  struct swig_type_info  *prev;
+} swig_type_info;
+
+#ifdef SWIG_NOINCLUDE
+SWIGEXPORT(swig_type_info *) SWIG_TypeRegister(swig_type_info *);
+SWIGEXPORT(swig_type_info *) SWIG_TypeCheck(char *c, swig_type_info *);
+SWIGEXPORT(void *) SWIG_TypeCast(swig_type_info *, void *);
+#else
+
+static swig_type_info *swig_type_list = 0;
+
+/* Register a type mapping with the type-checking */
+SWIGRUNTIME(swig_type_info *)
+SWIG_TypeRegister(swig_type_info *ti)
+{
+  swig_type_info *tc, *head, *ret, *next;
+  /* Check to see if this type has already been registered */
+  tc = swig_type_list;
+  while (tc) {
+    if (strcmp(tc->name, ti->name) == 0) {
+      /* Already exists in the table.  Just add additional types to the list */
+      head = tc;
+      next = tc->next;
+      goto l1;
+    }
+    tc = tc->prev;
+  }
+  head = ti;
+  next = 0;
+
+  /* Place in list */
+  ti->prev = swig_type_list;
+  swig_type_list = ti;
+
+  /* Build linked lists */
+ l1:
+  ret = head;
+  tc = ti + 1;
+  /* Patch up the rest of the links */
+  while (tc->name) {
+    head->next = tc;
+    tc->prev = head;
+    head = tc;
+    tc++;
+  }
+  head->next = next;
+  return ret;
+}
+
+/* Check the typename */
+SWIGRUNTIME(swig_type_info *) 
+SWIG_TypeCheck(char *c, swig_type_info *ty)
+{
+  swig_type_info *s;
+  if (!ty) return 0;        /* Void pointer */
+  s = ty->next;             /* First element always just a name */
+  while (s) {
+    if (strcmp(s->name,c) == 0) {
+      if (s == ty->next) return s;
+      /* Move s to the top of the linked list */
+      s->prev->next = s->next;
+      if (s->next) {
+	s->next->prev = s->prev;
+      }
+      /* Insert s as second element in the list */
+      s->next = ty->next;
+      if (ty->next) ty->next->prev = s;
+      ty->next = s;
+      return s;
+    }
+    s = s->next;
+  }
+  return 0;
+}
+
+/* Cast a pointer (needed for C++ inheritance */
+SWIGRUNTIME(void *) 
+SWIG_TypeCast(swig_type_info *ty, void *ptr) 
+{
+  if ((!ty) || (!ty->converter)) return ptr;
+  return (*ty->converter)(ptr);
+}
+
+/* Search for a swig_type_info structure */
+SWIGRUNTIME(void *)
+SWIG_TypeQuery(const char *name) {
+  swig_type_info *ty = swig_type_list;
+  while (ty) {
+    if (ty->str && (strcmp(name,ty->str) == 0)) return ty;
+    if (ty->name && (strcmp(name,ty->name) == 0)) return ty;
+    ty = ty->prev;
+  }
+  return 0;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+/***********************************************************************
+ * python.swg
+ *
+ *     This file contains the runtime support for Python modules
+ *     and includes code for managing global variables and pointer
+ *     type checking.
+ *
+ * Author : David Beazley (beazley at cs.uchicago.edu)
+ ************************************************************************/
+
+#include <stdlib.h>
+#include "Python.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SWIG_PY_INT     1
+#define SWIG_PY_FLOAT   2
+#define SWIG_PY_STRING  3
+#define SWIG_PY_POINTER 4
+
+/* Constant information structure */
+typedef struct swig_const_info {
+    int type;
+    char *name;
+    long lvalue;
+    double dvalue;
+    void   *pvalue;
+    swig_type_info **ptype;
+} swig_const_info;
+
+#ifdef SWIG_NOINCLUDE
+
+SWIGEXPORT(PyObject *)        SWIG_newvarlink();
+SWIGEXPORT(void)              SWIG_addvarlink(PyObject *, char *, PyObject *(*)(void), int (*)(PyObject *));
+SWIGEXPORT(int)               SWIG_ConvertPtr(PyObject *, void **, swig_type_info *, int);
+SWIGEXPORT(void)              SWIG_MakePtr(char *c, void *, swig_type_info *);
+SWIGEXPORT(PyObject *)        SWIG_NewPointerObj(void *, swig_type_info *);
+SWIGEXPORT(void)              SWIG_InstallConstants(PyObject *d, swig_const_info constants[]);
+
+#else
+
+/* -----------------------------------------------------------------------------
+ * global variable support code.
+ * ----------------------------------------------------------------------------- */
+
+typedef struct swig_globalvar {   
+  char       *name;                  /* Name of global variable */
+  PyObject *(*get_attr)(void);       /* Return the current value */
+  int       (*set_attr)(PyObject *); /* Set the value */
+  struct swig_globalvar *next;
+} swig_globalvar;
+
+typedef struct swig_varlinkobject {
+  PyObject_HEAD
+  swig_globalvar *vars;
+} swig_varlinkobject;
+
+static PyObject *
+swig_varlink_repr(swig_varlinkobject *v) {
+  v = v;
+  return PyString_FromString("<Global variables>");
+}
+
+static int
+swig_varlink_print(swig_varlinkobject *v, FILE *fp, int flags) {
+  swig_globalvar  *var;
+  flags = flags;
+  fprintf(fp,"Global variables { ");
+  for (var = v->vars; var; var=var->next) {
+    fprintf(fp,"%s", var->name);
+    if (var->next) fprintf(fp,", ");
+  }
+  fprintf(fp," }\n");
+  return 0;
+}
+
+static PyObject *
+swig_varlink_getattr(swig_varlinkobject *v, char *n) {
+  swig_globalvar *var = v->vars;
+  while (var) {
+    if (strcmp(var->name,n) == 0) {
+      return (*var->get_attr)();
+    }
+    var = var->next;
+  }
+  PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+  return NULL;
+}
+
+static int
+swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) {
+  swig_globalvar *var = v->vars;
+  while (var) {
+    if (strcmp(var->name,n) == 0) {
+      return (*var->set_attr)(p);
+    }
+    var = var->next;
+  }
+  PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+  return 1;
+}
+
+statichere PyTypeObject varlinktype = {
+  PyObject_HEAD_INIT(0)              
+  0,
+  "swigvarlink",                      /* Type name    */
+  sizeof(swig_varlinkobject),         /* Basic size   */
+  0,                                  /* Itemsize     */
+  0,                                  /* Deallocator  */ 
+  (printfunc) swig_varlink_print,     /* Print        */
+  (getattrfunc) swig_varlink_getattr, /* get attr     */
+  (setattrfunc) swig_varlink_setattr, /* Set attr     */
+  0,                                  /* tp_compare   */
+  (reprfunc) swig_varlink_repr,       /* tp_repr      */    
+  0,                                  /* tp_as_number */
+  0,                                  /* tp_as_mapping*/
+  0,                                  /* tp_hash      */
+};
+
+/* Create a variable linking object for use later */
+SWIGRUNTIME(PyObject *)
+SWIG_newvarlink(void) {
+  swig_varlinkobject *result = 0;
+  result = PyMem_NEW(swig_varlinkobject,1);
+  varlinktype.ob_type = &PyType_Type;    /* Patch varlinktype into a PyType */
+  result->ob_type = &varlinktype;
+  result->vars = 0;
+  result->ob_refcnt = 0;
+  Py_XINCREF((PyObject *) result);
+  return ((PyObject*) result);
+}
+
+SWIGRUNTIME(void)
+SWIG_addvarlink(PyObject *p, char *name,
+	   PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) {
+  swig_varlinkobject *v;
+  swig_globalvar *gv;
+  v= (swig_varlinkobject *) p;
+  gv = (swig_globalvar *) malloc(sizeof(swig_globalvar));
+  gv->name = (char *) malloc(strlen(name)+1);
+  strcpy(gv->name,name);
+  gv->get_attr = get_attr;
+  gv->set_attr = set_attr;
+  gv->next = v->vars;
+  v->vars = gv;
+}
+/* Convert a pointer value */
+SWIGRUNTIME(int)
+SWIG_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) {
+  unsigned long p;
+  register int d;
+  swig_type_info *tc;
+  char  *c;
+  static PyObject *SWIG_this = 0;
+  int    newref = 0;
+
+  if (!obj || (obj == Py_None)) {
+    *ptr = 0;
+    return 0;
+  }
+#ifdef SWIG_COBJECT_TYPES
+  if (!(PyCObject_Check(obj))) {
+    if (!SWIG_this)
+      SWIG_this = PyString_InternFromString("this");
+    obj = PyObject_GetAttr(obj,SWIG_this);
+    newref = 1;
+    if (!obj) goto type_error;
+    if (!PyCObject_Check(obj)) {
+      Py_DECREF(obj);
+      goto type_error;
+    }
+  } 
+  *ptr = PyCObject_AsVoidPtr(obj);
+  c = (char *) PyCObject_GetDesc(obj);
+  if (newref) Py_DECREF(obj);
+  goto cobject;
+#else
+  if (!(PyString_Check(obj))) {
+    if (!SWIG_this)
+      SWIG_this = PyString_InternFromString("this");
+    obj = PyObject_GetAttr(obj,SWIG_this);
+    newref = 1;
+    if (!obj) goto type_error;
+    if (!PyString_Check(obj)) {
+      Py_DECREF(obj);
+      goto type_error;
+    }
+  } 
+  c = PyString_AsString(obj);
+  p = 0;
+  /* Pointer values must start with leading underscore */
+  if (*c != '_') {
+    *ptr = (void *) 0;
+    if (strcmp(c,"NULL") == 0) {
+      if (newref) Py_DECREF(obj);
+      return 0;
+    } else {
+      if (newref) Py_DECREF(obj);
+      goto type_error;
+    }
+  }
+  c++;
+  /* Extract hex value from pointer */
+  while ((d = *c)) {
+    if ((d >= '0') && (d <= '9'))
+      p = (p << 4) + (d - '0');
+    else if ((d >= 'a') && (d <= 'f'))
+      p = (p << 4) + (d - ('a'-10));
+    else
+      break; 
+    c++;
+  }
+  *ptr = (void *) p;
+  if (newref) Py_DECREF(obj);
+#endif
+
+#ifdef SWIG_COBJECT_TYPES
+cobject:
+#endif
+
+  if (ty) {
+    tc = SWIG_TypeCheck(c,ty);
+    if (!tc) goto type_error;
+    *ptr = SWIG_TypeCast(tc,(void*)p);
+  }
+  return 0;
+
+type_error:
+
+  if (flags) {
+    if (ty) {
+      char *temp = (char *) malloc(64+strlen(ty->name));
+      sprintf(temp,"Type error. Expected %s", ty->name);
+      PyErr_SetString(PyExc_TypeError, temp);
+      free((char *) temp);
+    } else {
+      PyErr_SetString(PyExc_TypeError,"Expected a pointer");
+    }
+  }
+  return -1;
+}
+
+/* Take a pointer and convert it to a string */
+SWIGRUNTIME(void) 
+SWIG_MakePtr(char *c, void *ptr, swig_type_info *ty) {
+  static char hex[17] = "0123456789abcdef";
+  unsigned long p, s;
+  char result[32], *r; 
+  r = result;
+  p = (unsigned long) ptr;
+  if (p > 0) {
+    while (p > 0) {
+      s = p & 0xf;
+      *(r++) = hex[s];
+      p = p >> 4;
+    }
+    *r = '_';
+    while (r >= result)
+      *(c++) = *(r--);
+    strcpy (c, ty->name);
+  } else {
+    strcpy (c, "NULL");
+  }
+}
+
+/* Create a new pointer object */
+SWIGRUNTIME(PyObject *)
+SWIG_NewPointerObj(void *ptr, swig_type_info *type) {
+  char result[512];
+  PyObject *robj;
+  if (!ptr) {
+    Py_INCREF(Py_None);
+    return Py_None;
+  }
+#ifdef SWIG_COBJECT_TYPES
+  robj = PyCObject_FromVoidPtrAndDesc((void *) ptr, type->name, NULL);
+#else
+  SWIG_MakePtr(result,ptr,type);
+  robj = PyString_FromString(result);
+#endif
+  return robj;
+}
+
+/* Install Constants */
+SWIGRUNTIME(void)
+SWIG_InstallConstants(PyObject *d, swig_const_info constants[]) {
+  int i;
+  PyObject *obj;
+  for (i = 0; constants[i].type; i++) {
+    switch(constants[i].type) {
+    case SWIG_PY_INT:
+      obj = PyInt_FromLong(constants[i].lvalue);
+      break;
+    case SWIG_PY_FLOAT:
+      obj = PyFloat_FromDouble(constants[i].dvalue);
+      break;
+    case SWIG_PY_STRING:
+      obj = PyString_FromString((char *) constants[i].pvalue);
+      break;
+    case SWIG_PY_POINTER:
+      obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype);
+      break;
+    default:
+      obj = 0;
+      break;
+    }
+    if (obj) {
+      PyDict_SetItemString(d,constants[i].name,obj);
+      Py_DECREF(obj);
+    }
+  }
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+/* -------- TYPES TABLE (BEGIN) -------- */
+
+#define  SWIGTYPE_p_DBFFile swig_types[0] 
+static swig_type_info *swig_types[2];
+
+/* -------- TYPES TABLE (END) -------- */
+
+
+/*-----------------------------------------------
+              @(target):= dbflibc.so
+  ------------------------------------------------*/
+#define SWIG_init    initdbflibc
+
+#define SWIG_name    "dbflibc"
+
+#include "shapefil.h"
+
+
+/* Read one attribute from the dbf handle and return it as a new python object
+ *
+ * If an error occurs, set the appropriate Python exception and return
+ * NULL.
+ *
+ * Assume that the values of the record and field arguments are valid.
+ * The name argument will be passed to DBFGetFieldInfo as is and should
+ * thus be either NULL or a pointer to an array of at least 12 chars
+ */
+static PyObject *
+do_read_attribute(DBFInfo * handle, int record, int field, char * name)
+{
+    int type, width;
+    PyObject *value;
+
+    type = DBFGetFieldInfo(handle, field, name, &width, NULL);
+    /* For strings NULL and the empty string are indistinguishable
+     * in DBF files. We prefer empty strings instead for backwards
+     * compatibility reasons because older wrapper versions returned
+     * emtpy strings as empty strings.
+     */
+    if (type != FTString && DBFIsAttributeNULL(handle, record, field))
+    {
+	value = Py_None;
+	Py_INCREF(value);
+    }
+    else
+    {
+	switch (type)
+	{
+	case FTString:
+	{
+	    const char * temp = DBFReadStringAttribute(handle, record, field);
+	    if (temp)
+	    {
+		value = PyString_FromString(temp);
+	    }
+	    else
+	    {
+		PyErr_Format(PyExc_IOError,
+			     "Can't read value for row %d column %d",
+			     record, field);
+		value = NULL;
+	    }
+	    break;
+	}
+	case FTInteger:
+	    value = PyInt_FromLong(DBFReadIntegerAttribute(handle, record,
+							   field));
+	    break;
+	case FTDouble:
+	    value = PyFloat_FromDouble(DBFReadDoubleAttribute(handle, record,
+							      field));
+	    break;
+	default:
+	    PyErr_Format(PyExc_TypeError, "Invalid field data type %d",
+			 type);
+	    value = NULL;
+	}
+    }
+    if (!value)
+	return NULL;
+
+    return value;
+}    
+
+/* the read_attribute method. Return the value of the given record and
+ * field as a python object of the appropriate type.
+ * 
+ * In case of error, set a python exception and return NULL. Since that
+ * value will be returned to the python interpreter as is, the
+ * interpreter should recognize the exception.
+ */
+
+static PyObject *
+DBFInfo_read_attribute(DBFInfo * handle, int record, int field)
+{
+    if (record < 0 || record >= DBFGetRecordCount(handle))
+    {
+	PyErr_Format(PyExc_ValueError,
+		     "record index %d out of bounds (record count: %d)",
+		     record, DBFGetRecordCount(handle));
+	return NULL;
+    }
+
+    if (field < 0 || field >= DBFGetFieldCount(handle))
+    {
+	PyErr_Format(PyExc_ValueError,
+		     "field index %d out of bounds (field count: %d)",
+		     field, DBFGetFieldCount(handle));
+	return NULL;
+    }
+
+    return do_read_attribute(handle, record, field, NULL);
+}
+    
+
+/* the read_record method. Return the record record as a dictionary with
+ * whose keys are the names of the fields, and their values as the
+ * appropriate Python type.
+ * 
+ * In case of error, set a python exception and return NULL. Since that
+ * value will be returned to the python interpreter as is, the
+ * interpreter should recognize the exception.
+ */
+
+static PyObject *
+DBFInfo_read_record(DBFInfo * handle, int record)
+{
+    int num_fields;
+    int i;
+    int type, width;
+    char name[12];
+    PyObject *dict;
+    PyObject *value;
+
+    if (record < 0 || record >= DBFGetRecordCount(handle))
+    {
+	PyErr_Format(PyExc_ValueError,
+		     "record index %d out of bounds (record count: %d)",
+		     record, DBFGetRecordCount(handle));
+	return NULL;
+    }
+
+    dict = PyDict_New();
+    if (!dict)
+	return NULL;
+	
+    num_fields = DBFGetFieldCount(handle);
+    for (i = 0; i < num_fields; i++)
+    {
+	value = do_read_attribute(handle, record, i, name);
+	if (!value)
+	    goto fail;
+
+	PyDict_SetItemString(dict, name, value);
+	Py_DECREF(value);
+    }
+
+    return dict;
+
+ fail:
+    Py_XDECREF(dict);
+    return NULL;
+}
+
+/* the write_record method. Write the record record given wither as a
+ * dictionary or a sequence (i.e. a list or a tuple).
+ *
+ * If it's a dictionary the keys must be the names of the fields and
+ * their value must have a suitable type. Only the fields actually
+ * contained in the dictionary are written. Fields for which there's no
+ * item in the dict are not modified.
+ *
+ * If it's a sequence, all fields must be present in the right order.
+ *
+ * In case of error, set a python exception and return NULL. Since that
+ * value will be returned to the python interpreter as is, the
+ * interpreter should recognize the exception.
+ *
+ * The method is implemented with two c-functions, write_field to write
+ * a single field and DBFInfo_write_record as the front-end.
+ */
+
+
+/* write a single field of a record. */
+static int
+write_field(DBFHandle handle, int record, int field, int type,
+	    PyObject * value)
+{
+    char * string_value;
+    int int_value;
+    double double_value;
+
+    if (value == Py_None)
+    {
+	if (!DBFWriteNULLAttribute(handle, record, field))
+	{
+	    PyErr_Format(PyExc_IOError,
+			 "can't write NULL field %d of record %d",
+			 field, record);
+	    return 0;
+	}
+    }
+    else
+    {
+	switch (type)
+	{
+	case FTString:
+	    string_value = PyString_AsString(value);
+	    if (!string_value)
+		return 0;
+	    if (!DBFWriteStringAttribute(handle, record, field, string_value))
+	    {
+		PyErr_Format(PyExc_IOError,
+			     "can't write field %d of record %d",
+			     field, record);
+		return 0;
+	    }
+	    break;
+
+	case FTInteger:
+	    int_value = PyInt_AsLong(value);
+	    if (int_value == -1 && PyErr_Occurred())
+		return 0;
+	    if (!DBFWriteIntegerAttribute(handle, record, field, int_value))
+	    {
+		PyErr_Format(PyExc_IOError,
+			     "can't write field %d of record %d",
+			     field, record);
+		return 0;
+	    }
+	    break;
+
+	case FTDouble:
+	    double_value = PyFloat_AsDouble(value);
+	    if (double_value == -1 && PyErr_Occurred())
+		return 0;
+	    if (!DBFWriteDoubleAttribute(handle, record, field, double_value))
+	    {
+		PyErr_Format(PyExc_IOError,
+			     "can't write field %d of record %d",
+			     field, record);
+		return 0;
+	    }
+	    break;
+
+	default:
+	    PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);
+	    return 0;
+	}
+    }
+
+    return 1;
+}
+
+static
+PyObject *
+DBFInfo_write_record(DBFHandle handle, int record, PyObject *record_object)
+{
+    int num_fields;
+    int i, length;
+    int type, width;
+    char name[12];
+    PyObject * value = NULL;
+
+    num_fields = DBFGetFieldCount(handle);
+
+    /* We used to use PyMapping_Check to test whether record_object is a
+     * dictionary like object instead of PySequence_Check to test
+     * whether it's a sequence. Unfortunately in Python 2.3
+     * PyMapping_Check returns true for lists and tuples too so the old
+     * approach doesn't work anymore.
+     */
+    if (PySequence_Check(record_object))
+    {
+	/* It's a sequence object. Iterate through all items in the
+	 * sequence and write them to the appropriate field.
+	 */
+	length = PySequence_Length(record_object);
+	if (length != num_fields)
+	{
+	    PyErr_SetString(PyExc_TypeError,
+			    "record must have one item for each field");
+	    goto fail;
+	}
+	for (i = 0; i < length; i++)
+	{
+	    type = DBFGetFieldInfo(handle, i, name, &width, NULL); 
+	    value = PySequence_GetItem(record_object, i);
+	    if (value)
+	    {
+		if (!write_field(handle, record, i, type, value))
+		    goto fail;
+		Py_DECREF(value);
+	    }
+	    else
+	    {
+		goto fail;
+	    }
+	}
+    }
+    else
+    {
+	/* It's a dictionary-like object. Iterate over the names of the
+         * known fields and write the corresponding item
+	 */
+	for (i = 0; i < num_fields; i++)
+	{
+	    type = DBFGetFieldInfo(handle, i, name, &width, NULL);
+
+	    /* if the dictionary has the key name write that object to
+	     * the appropriate field, other wise just clear the python
+	     * exception and do nothing.
+	     */
+	    value = PyMapping_GetItemString(record_object, name);
+	    if (value)
+	    {
+		if (!write_field(handle, record, i, type, value))
+		    goto fail;
+		Py_DECREF(value);
+	    }
+	    else
+	    {
+		PyErr_Clear();
+	    }
+	}
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+
+ fail:
+    Py_XDECREF(value);
+    return NULL;
+}
+
+static
+void
+DBFInfo_commit(DBFHandle handle)
+{
+#if HAVE_UPDATE_HEADER
+    DBFUpdateHeader(handle);
+#endif
+}
+
+static PyObject* l_output_helper(PyObject* target, PyObject* o) {
+    PyObject*   o2;
+    if (!target) {                   
+        target = o;
+    } else if (target == Py_None) {  
+        Py_DECREF(Py_None);
+        target = o;
+    } else {                         
+        if (!PyList_Check(target)) {
+            o2 = target;
+            target = PyList_New(0);
+            PyList_Append(target, o2);
+	    Py_XDECREF(o2);
+        }
+        PyList_Append(target,o);
+	Py_XDECREF(o);
+    }
+    return target;
+}
+
+static PyObject* t_output_helper(PyObject* target, PyObject* o) {
+    PyObject*   o2;
+    PyObject*   o3;
+
+    if (!target) {                   
+        target = o;
+    } else if (target == Py_None) {  
+        Py_DECREF(Py_None);
+        target = o;
+    } else {                         
+        if (!PyTuple_Check(target)) {
+            o2 = target;
+            target = PyTuple_New(1);
+            PyTuple_SetItem(target, 0, o2);
+        }
+        o3 = PyTuple_New(1);            
+        PyTuple_SetItem(o3, 0, o);      
+
+        o2 = target;
+        target = PySequence_Concat(o2, o3); 
+        Py_DECREF(o2);                      
+        Py_DECREF(o3);
+    }
+    return target;
+}
+
+#define  SWIG_MemoryError    1
+#define  SWIG_IOError        2
+#define  SWIG_RuntimeError   3
+#define  SWIG_IndexError     4
+#define  SWIG_TypeError      5
+#define  SWIG_DivisionByZero 6
+#define  SWIG_OverflowError  7
+#define  SWIG_SyntaxError    8
+#define  SWIG_ValueError     9
+#define  SWIG_SystemError   10
+#define  SWIG_UnknownError  99
+
+static void _SWIG_exception(int code, char *msg) {
+  switch(code) {
+  case SWIG_MemoryError:
+    PyErr_SetString(PyExc_MemoryError,msg);
+    break;
+  case SWIG_IOError:
+    PyErr_SetString(PyExc_IOError,msg);
+    break;
+  case SWIG_RuntimeError:
+    PyErr_SetString(PyExc_RuntimeError,msg);
+    break;
+  case SWIG_IndexError:
+    PyErr_SetString(PyExc_IndexError,msg);
+    break;
+  case SWIG_TypeError:
+    PyErr_SetString(PyExc_TypeError,msg);
+    break;
+  case SWIG_DivisionByZero:
+    PyErr_SetString(PyExc_ZeroDivisionError,msg);
+    break;
+  case SWIG_OverflowError:
+    PyErr_SetString(PyExc_OverflowError,msg);
+    break;
+  case SWIG_SyntaxError:
+    PyErr_SetString(PyExc_SyntaxError,msg);
+    break;
+  case SWIG_ValueError:
+    PyErr_SetString(PyExc_ValueError,msg);
+    break;
+  case SWIG_SystemError:
+    PyErr_SetString(PyExc_SystemError,msg);
+    break;
+  default:
+    PyErr_SetString(PyExc_RuntimeError,msg);
+    break;
+  }
+}
+
+#define SWIG_exception(a,b) { _SWIG_exception(a,b); return NULL; }
+
+    typedef struct {
+	DBFHandle handle;
+    } DBFFile;
+
+#define NOCHECK_delete_DBFFile
+#define NOCHECK_DBFFile_close
+
+    DBFFile * open_DBFFile(const char * file, const char * mode)
+    {
+	DBFFile * self = malloc(sizeof(DBFFile));
+	if (self)
+	    self->handle = DBFOpen(file, mode);
+	return self;
+    }
+
+    DBFFile * create_DBFFile(const char * file)
+    {
+	DBFFile * self = malloc(sizeof(DBFFile));
+	if (self)
+	    self->handle = DBFCreate(file);
+	return self;
+    }
+#ifdef __cplusplus
+extern "C" {
+#endif
+static PyObject *_wrap_open(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    char *arg0 ;
+    char *arg1 = "rb" ;
+    DBFFile *result ;
+    
+    if(!PyArg_ParseTuple(args,"s|s:open",&arg0,&arg1)) return NULL;
+    {
+        result = (DBFFile *)open_DBFFile((char const *)arg0,(char const *)arg1);
+        ;
+        if (!result)
+        {
+            SWIG_exception(SWIG_MemoryError, "no memory");
+        }
+        else if (!result->handle)
+        {
+            SWIG_exception(SWIG_IOError, "open_DBFFile failed");
+        }
+    }resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_DBFFile);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_create(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    char *arg0 ;
+    DBFFile *result ;
+    
+    if(!PyArg_ParseTuple(args,"s:create",&arg0)) return NULL;
+    {
+        result = (DBFFile *)create_DBFFile((char const *)arg0);
+        ;
+        if (!result)
+        {
+            SWIG_exception(SWIG_MemoryError, "no memory");
+        }
+        else if (!result->handle)
+        {
+            SWIG_exception(SWIG_IOError, "create_DBFFile failed");
+        }
+    }resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_DBFFile);
+    return resultobj;
+}
+
+
+DBFFile * new_DBFFile(char const *file,char const *mode) {
+    {
+        DBFFile * self = malloc(sizeof(DBFFile));
+        if (self)
+        self->handle = DBFOpen(file, mode);
+        return self;
+    }
+}
+
+
+static PyObject *_wrap_new_DBFFile(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    char *arg0 ;
+    char *arg1 = "rb" ;
+    DBFFile *result ;
+    
+    if(!PyArg_ParseTuple(args,"s|s:new_DBFFile",&arg0,&arg1)) return NULL;
+    {
+        result = (DBFFile *)new_DBFFile((char const *)arg0,(char const *)arg1);
+        ;
+        if (!result)
+        {
+            SWIG_exception(SWIG_MemoryError, "no memory");
+        }
+        else if (!result->handle)
+        {
+            SWIG_exception(SWIG_IOError, "new_DBFFile failed");
+        }
+    }resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_DBFFile);
+    return resultobj;
+}
+
+
+void  delete_DBFFile(DBFFile *self) {
+    {
+        if (self->handle)
+        DBFClose(self->handle);
+        free(self);
+    }
+}
+
+
+static PyObject *_wrap_delete_DBFFile(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    DBFFile *arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:delete_DBFFile",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_DBFFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_delete_DBFFile
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "dbffile already closed");
+        #endif
+    }
+    delete_DBFFile(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+void  DBFFile_close(DBFFile *self) {
+    {
+        if (self->handle)
+        DBFClose(self->handle);
+        self->handle = NULL;
+    }
+}
+
+
+static PyObject *_wrap_DBFFile_close(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    DBFFile *arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:DBFFile_close",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_DBFFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_DBFFile_close
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "dbffile already closed");
+        #endif
+    }
+    DBFFile_close(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+int  DBFFile_field_count(DBFFile *self) {
+    {
+        return DBFGetFieldCount(self->handle);
+    }
+}
+
+
+static PyObject *_wrap_DBFFile_field_count(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    DBFFile *arg0 ;
+    PyObject * argo0 =0 ;
+    int result ;
+    
+    if(!PyArg_ParseTuple(args,"O:DBFFile_field_count",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_DBFFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_DBFFile_field_count
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "dbffile already closed");
+        #endif
+    }
+    result = (int )DBFFile_field_count(arg0);
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+}
+
+
+int  DBFFile_record_count(DBFFile *self) {
+    {
+        return DBFGetRecordCount(self->handle);
+    }
+}
+
+
+static PyObject *_wrap_DBFFile_record_count(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    DBFFile *arg0 ;
+    PyObject * argo0 =0 ;
+    int result ;
+    
+    if(!PyArg_ParseTuple(args,"O:DBFFile_record_count",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_DBFFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_DBFFile_record_count
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "dbffile already closed");
+        #endif
+    }
+    result = (int )DBFFile_record_count(arg0);
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+}
+
+
+int  DBFFile_field_info(DBFFile *self,int iField,char *fieldname_out,int *output_width,int *output_decimals) {
+    {
+        return DBFGetFieldInfo(self->handle, iField, fieldname_out,
+        output_width, output_decimals);
+    }
+}
+
+
+static PyObject *_wrap_DBFFile_field_info(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    DBFFile *arg0 ;
+    int arg1 ;
+    char *arg2 ;
+    int *arg3 ;
+    int *arg4 ;
+    char temp[12] ;
+    int temp0 ;
+    int temp1 ;
+    PyObject * argo0 =0 ;
+    int result ;
+    
+    {
+        arg2 = temp;
+    }
+    {
+        arg3 = &temp0;
+    }
+    {
+        arg4 = &temp1;
+    }
+    if(!PyArg_ParseTuple(args,"Oi:DBFFile_field_info",&argo0,&arg1)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_DBFFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_DBFFile_field_info
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "dbffile already closed");
+        #endif
+    }
+    result = (int )DBFFile_field_info(arg0,arg1,arg2,arg3,arg4);
+    resultobj = PyInt_FromLong((long)result);
+    {
+        PyObject * string = PyString_FromString(arg2);
+        resultobj = t_output_helper(resultobj,string);
+    }
+    {
+        PyObject *o;
+        o = PyInt_FromLong((long) (*arg3));
+        resultobj = t_output_helper(resultobj, o);
+    }
+    {
+        PyObject *o;
+        o = PyInt_FromLong((long) (*arg4));
+        resultobj = t_output_helper(resultobj, o);
+    }
+    return resultobj;
+}
+
+
+PyObject * DBFFile_read_record(DBFFile *self,int record) {
+    {
+        return DBFInfo_read_record(self->handle, record);
+    }
+}
+
+
+static PyObject *_wrap_DBFFile_read_record(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    DBFFile *arg0 ;
+    int arg1 ;
+    PyObject * argo0 =0 ;
+    PyObject *result ;
+    
+    if(!PyArg_ParseTuple(args,"Oi:DBFFile_read_record",&argo0,&arg1)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_DBFFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_DBFFile_read_record
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "dbffile already closed");
+        #endif
+    }
+    result = (PyObject *)DBFFile_read_record(arg0,arg1);
+    {
+        resultobj = result;
+    }
+    return resultobj;
+}
+
+
+PyObject * DBFFile_read_attribute(DBFFile *self,int record,int field) {
+    {
+        return DBFInfo_read_attribute(self->handle, record, field);
+    }
+}
+
+
+static PyObject *_wrap_DBFFile_read_attribute(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    DBFFile *arg0 ;
+    int arg1 ;
+    int arg2 ;
+    PyObject * argo0 =0 ;
+    PyObject *result ;
+    
+    if(!PyArg_ParseTuple(args,"Oii:DBFFile_read_attribute",&argo0,&arg1,&arg2)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_DBFFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_DBFFile_read_attribute
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "dbffile already closed");
+        #endif
+    }
+    result = (PyObject *)DBFFile_read_attribute(arg0,arg1,arg2);
+    {
+        resultobj = result;
+    }
+    return resultobj;
+}
+
+
+int  DBFFile_add_field(DBFFile *self,char const *pszFieldName,DBFFieldType eType,int nWidth,int nDecimals) {
+    {
+        return DBFAddField(self->handle, pszFieldName, eType, nWidth,
+        nDecimals);
+    }
+}
+
+
+static PyObject *_wrap_DBFFile_add_field(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    DBFFile *arg0 ;
+    char *arg1 ;
+    int arg2 ;
+    int arg3 ;
+    int arg4 ;
+    PyObject * argo0 =0 ;
+    int result ;
+    
+    if(!PyArg_ParseTuple(args,"Osiii:DBFFile_add_field",&argo0,&arg1,&arg2,&arg3,&arg4)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_DBFFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_DBFFile_add_field
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "dbffile already closed");
+        #endif
+    }
+    {
+        result = (int )DBFFile_add_field(arg0,(char const *)arg1,(DBFFieldType )arg2,arg3,arg4);
+        ;
+        if (result < 0)
+        {
+            SWIG_exception(SWIG_RuntimeError, "add_field failed");
+        }
+    }resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+}
+
+
+PyObject * DBFFile_write_record(DBFFile *self,int record,PyObject *dict_or_sequence) {
+    {
+        return DBFInfo_write_record(self->handle, record,
+        dict_or_sequence);
+    }
+}
+
+
+static PyObject *_wrap_DBFFile_write_record(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    DBFFile *arg0 ;
+    int arg1 ;
+    PyObject *arg2 ;
+    PyObject * argo0 =0 ;
+    PyObject * obj2  = 0 ;
+    PyObject *result ;
+    
+    if(!PyArg_ParseTuple(args,"OiO:DBFFile_write_record",&argo0,&arg1,&obj2)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_DBFFile,1)) == -1) return NULL;
+    {
+        arg2 = obj2;
+    }
+    {
+        #ifndef NOCHECK_DBFFile_write_record
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "dbffile already closed");
+        #endif
+    }
+    result = (PyObject *)DBFFile_write_record(arg0,arg1,arg2);
+    {
+        resultobj = result;
+    }
+    return resultobj;
+}
+
+
+void  DBFFile_commit(DBFFile *self) {
+    {
+        DBFInfo_commit(self->handle);
+    }
+}
+
+
+static PyObject *_wrap_DBFFile_commit(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    DBFFile *arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:DBFFile_commit",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_DBFFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_DBFFile_commit
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "dbffile already closed");
+        #endif
+    }
+    DBFFile_commit(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+static PyMethodDef dbflibcMethods[] = {
+	 { "open", _wrap_open, METH_VARARGS },
+	 { "create", _wrap_create, METH_VARARGS },
+	 { "new_DBFFile", _wrap_new_DBFFile, METH_VARARGS },
+	 { "delete_DBFFile", _wrap_delete_DBFFile, METH_VARARGS },
+	 { "DBFFile_close", _wrap_DBFFile_close, METH_VARARGS },
+	 { "DBFFile_field_count", _wrap_DBFFile_field_count, METH_VARARGS },
+	 { "DBFFile_record_count", _wrap_DBFFile_record_count, METH_VARARGS },
+	 { "DBFFile_field_info", _wrap_DBFFile_field_info, METH_VARARGS },
+	 { "DBFFile_read_record", _wrap_DBFFile_read_record, METH_VARARGS },
+	 { "DBFFile_read_attribute", _wrap_DBFFile_read_attribute, METH_VARARGS },
+	 { "DBFFile_add_field", _wrap_DBFFile_add_field, METH_VARARGS },
+	 { "DBFFile_write_record", _wrap_DBFFile_write_record, METH_VARARGS },
+	 { "DBFFile_commit", _wrap_DBFFile_commit, METH_VARARGS },
+	 { NULL, NULL }
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
+
+static swig_type_info _swigt__p_DBFFile[] = {{"_p_DBFFile", 0, "DBFFile *"},{"_p_DBFFile"},{0}};
+
+static swig_type_info *swig_types_initial[] = {
+_swigt__p_DBFFile, 
+0
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
+
+static swig_const_info swig_const_table[] = {
+    { SWIG_PY_INT,     "FTString", (long) FTString, 0, 0, 0},
+    { SWIG_PY_INT,     "FTInteger", (long) FTInteger, 0, 0, 0},
+    { SWIG_PY_INT,     "FTDouble", (long) FTDouble, 0, 0, 0},
+    { SWIG_PY_INT,     "FTInvalid", (long) FTInvalid, 0, 0, 0},
+    { SWIG_PY_INT,     "_have_commit", (long) HAVE_UPDATE_HEADER, 0, 0, 0},
+{0}};
+
+static PyObject *SWIG_globals;
+#ifdef __cplusplus
+extern "C" 
+#endif
+SWIGEXPORT(void) initdbflibc(void) {
+    PyObject *m, *d;
+    int i;
+    SWIG_globals = SWIG_newvarlink();
+    m = Py_InitModule("dbflibc", dbflibcMethods);
+    d = PyModule_GetDict(m);
+    for (i = 0; swig_types_initial[i]; i++) {
+        swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);
+    }
+    SWIG_InstallConstants(d,swig_const_table);
+
+#   if PY_VERSION_HEX >=0x02040000 
+    /* because we are in a python module now, we can give out
+     * pointers to python's locale agonistic function 
+     * XXX this clearly is a hack
+     */
+    DBFSetatof_function(&PyOS_ascii_atof);
+#   endif
+
+}
+

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/pyshapelib_api.h
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/pyshapelib_api.h	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/pyshapelib_api.h	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,41 @@
+/* Header file for the PyShapelib API for other Python modules */
+/* $Revision: 1611 $ */
+
+#ifndef PYSHAPELIB_API_H
+#define PYSHAPELIB_API_H
+
+typedef struct {
+    /* Shapefile functions */
+    SHPObject * (*SHPReadObject)(SHPHandle hSHP, int iShape);
+    void (*SHPDestroyObject)(SHPObject * psObject);
+
+    /* SHPTree functions */
+    SHPTree * (*SHPCreateTree)(SHPHandle hSHP, int nDimension, int nMaxDepth,
+			       double *padfBoundsMin, double *padfBoundsMax);
+    void (*SHPDestroyTree)(SHPTree * hTree);
+    int * (*SHPTreeFindLikelyShapes)(SHPTree * hTree, double * padfBoundsMin,
+				     double * padfBoundsMax, int *);
+} PyShapeLibAPI;
+
+
+/* Macro to import the shapelib module, extract the API pointer and
+ * assign it to the variable given as argument */
+#define PYSHAPELIB_IMPORT_API(apivariable)				   \
+{									   \
+    PyObject * shapelib = PyImport_ImportModule("shapelibc");		   \
+    if (shapelib)							   \
+    {									   \
+	PyObject * c_api_func = PyObject_GetAttrString(shapelib, "c_api"); \
+	if (c_api_func)							   \
+	{								   \
+	    PyObject * cobj = PyObject_CallObject(c_api_func, NULL);	   \
+	    if (cobj)							   \
+	    {								   \
+		(apivariable) = (PyShapeLibAPI*)PyCObject_AsVoidPtr(cobj); \
+	    }								   \
+	}								   \
+    }									   \
+}
+
+
+#endif /* PYSHAPELIB_API_H */

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/pytest.py
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/pytest.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/pytest.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,128 @@
+import shapelib, dbflib, shptree
+
+#
+#       The the shapefile module
+#
+
+def make_shapefile(filename):
+    # Create a shapefile with polygons
+    outfile = shapelib.create(filename, shapelib.SHPT_POLYGON)
+
+    # Create one very simple polygon and write it to the shapefile.  The
+    # vertices should be given in clockwise order to comply with the
+    # shapefile specification.
+    obj = shapelib.SHPObject(shapelib.SHPT_POLYGON, 1,
+                             [[(10, 10), (10, 20), (20, 20), (10, 10)]])
+    print obj.extents()
+    print obj.vertices()
+    outfile.write_object(-1, obj)
+
+    # Create a polygon with a hole.  Note that according to the
+    # shapefile specification, the vertices of the outer ring have to be
+    # in clockwise order and the inner rings have to be in counter
+    # clockwise order.
+    #
+    # There's an optional fourth parameter which when given must be a
+    # list of part types, one for each part of the shape.  For polygons,
+    # the part type is always shapelib.SHPP_RING, though.  The part
+    # types are only relevant for SHPT_MULTIPATCH shapefiles.
+    obj = shapelib.SHPObject(shapelib.SHPT_POLYGON, 1,
+                             [[(0, 0), (0, 40), (40, 40), (40, 0), (0, 0)],
+                              [(10, 10), (20, 10), (20, 20), (10, 20),(10, 10)],
+                              ])
+    print obj.extents()
+    print obj.vertices()
+    outfile.write_object(-1, obj)
+
+    # close the file.
+    outfile.close()
+
+def read_shapefile(filename):
+    # open the shapefile
+    shp = shapelib.ShapeFile(filename)
+
+    # the info method returns a tuple (num_shapes, type, min, max) where
+    # num_shapes is the number of shapes, type is the type code (one of
+    # the SHPT* constants defined in the shapelib module) and min and
+    # max are 4-element lists with the min. and max. values of the
+    # vertices.
+    print shp.info()
+
+    # read_object reads a shape
+    obj = shp.read_object(0)
+
+    # The vertices method returns the shape as a list of lists of tuples.
+    print obj.vertices()[0][:10]
+
+    # The extents returns a tuple with two 4-element lists with the min.
+    # and max. values of the vertices.
+    print obj.extents()
+
+    # The type attribute is the type code (one of the SHPT* constants
+    # defined in the shapelib module)
+    print obj.type
+
+    # The id attribute is the shape id
+    print obj.id
+
+    # the cobject method returns a PyCObject containing the shapelib
+    # SHPHandle. This is useful for passing shapefile objects to
+    # C-Python extensions.
+    print shp.cobject()
+
+    # build a quad tree from the shapefile. The first argument must be
+    # the return value of the shape file object's cobject method (this
+    # is currently needed to access the shape file at the C-level). The
+    # second argument is the dimension and the third the maximum depth.
+    # 0 means to guess an appropriate depth
+    tree = shptree.SHPTree(shp.cobject(), 2, 0)
+
+    # Retrieve the ids for a region. Here we just use the extents of the
+    # object previously read from the shapefile
+    minima, maxima = obj.extents()
+    print tree.find_shapes(minima[:2], maxima[:2])
+
+
+make_shapefile("testfile")
+read_shapefile("testfile")
+
+#
+#       Test the DBF file module.
+#
+
+def make_dbf(file):
+    # create a new dbf file and add three fields.
+    dbf = dbflib.create(file)
+    dbf.add_field("NAME", dbflib.FTString, 20, 0)
+    dbf.add_field("INT", dbflib.FTInteger, 10, 0)
+    dbf.add_field("FLOAT", dbflib.FTDouble, 10, 4)
+
+def add_dbf_records(file):
+    # add some records to file
+    dbf = dbflib.open(file, "r+b")
+    # Records can be added as a dictionary...
+    dbf.write_record(0, {'NAME': "Weatherwax", "INT":1, "FLOAT":3.1415926535})
+    # ... or as a sequence
+    dbf.write_record(1, ("Ogg", 2, -1000.1234))
+
+def list_dbf(file):
+    # print the contents of a dbf file to stdout
+    dbf = dbflib.DBFFile(file)
+    print "%d records, %d fields" % (dbf.record_count(), dbf.field_count())
+    format = ""
+    for i in range(dbf.field_count()):
+        type, name, len, decc = dbf.field_info(i)
+        if type == 0:
+            format = format + " %%(%s)%ds" % (name, len)
+        elif type == 1:
+            format = format + " %%(%s)%dd" % (name, len)
+        elif type == 2:
+            format = format + " %%(%s)%dg" % (name, len)
+    print format
+    for i in range(dbf.record_count()):
+        print format % dbf.read_record(i)
+
+
+make_dbf("testfile")
+add_dbf_records("testfile")
+list_dbf("testfile")

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/setup.py
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/setup.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/setup.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,72 @@
+
+import os
+import sys
+from distutils.core import setup, Extension
+from distutils.util import convert_path
+
+# try to determine the directory where the shapelib source files are.
+# There are currently two supported situations.
+#
+# 1. "Standalone" build: the parent directory is the shapelib source
+#    directory
+# 2. Built in the Thuban source tree where ../shapelib/ relative to the
+#    directory containing this setup.py contains (the relevant parts of)
+#    shapelib
+#
+# 3. Binary build with e.g. bdist_rpm.  This takes place deep in the
+#    build directory.
+
+# os.path expects filenames in OS-specific form so we have to construct
+# the files with os.path functions. distutils, OTOH, uses posix-style
+# filenames exclusively, so we use posix conventions when making
+# filenames for distutils.
+for shp_dir in ["..", "../shapelib", "../../../../../../shapelib"]:
+    if (os.path.isdir(convert_path(shp_dir))
+        and os.path.exists(os.path.join(convert_path(shp_dir), "shpopen.c"))):
+        # shp_dir contains shpopen.c, so assume it's the directory with
+        # the shapefile library to use
+        break
+else:
+    print >>sys.stderr, "no shapelib directory found"
+    sys.exit(1)
+
+def dbf_macros():
+    """Return the macros to define when compiling the dbflib wrapper.
+
+    The returned list specifies one macro, HAVE_UPDATE_HEADER, which is
+    '1' if the dbflib version we will be compiling with has the
+    DBFUpdateHeader function and '0' otherwise.  To check whether
+    DBFUpdateHeader is available, we scan shapefil.h for the string
+    'DBFUpdateHeader'.
+    """
+    f = open(convert_path(shp_dir + "/shapefil.h"))
+    contents = f.read()
+    f.close()
+    if contents.find("DBFUpdateHeader") >= 0:
+        return [("HAVE_UPDATE_HEADER", "1")]
+    else:
+        return [("HAVE_UPDATE_HEADER", "0")]
+
+extensions = [Extension("shapelibc",
+                        ["shapelib_wrap.c",
+                         shp_dir + "/shpopen.c",
+                         shp_dir + "/shptree.c"],
+                        include_dirs = [shp_dir]),
+              Extension("shptree",
+                        ["shptreemodule.c"],
+                        include_dirs = [shp_dir]),
+              Extension("dbflibc",
+                        ["dbflib_wrap.c",
+                         shp_dir + "/dbfopen.c"],
+                        include_dirs = [shp_dir],
+                        define_macros = dbf_macros())]
+
+setup(name = "pyshapelib",
+      version = "0.3",
+      description = "Python bindings for shapelib",
+      author = "Bernhard Herzog",
+      author_email = "bh at intevation.de",
+      url = "ftp:intevation.de/users/bh",
+      py_modules = ["shapelib", "dbflib"],
+      ext_modules = extensions)
+

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib.i
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib.i	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib.i	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,612 @@
+/* SWIG (www.swig.org) interface file for shapelib
+ *
+ * At the moment (Dec 2000) this file is only useful to generate Python
+ * bindings. Invoke swig as follows:
+ *
+ *	swig -python -shadow shapelib.i
+ *
+ * to generate shapelib_wrap.c and shapelib.py. shapelib_wrap.c
+ * defines a bunch of Python-functions that wrap the appripriate
+ * shapelib functions and shapelib.py contains an object oriented
+ * wrapper around shapelib_wrap.c.
+ *
+ * Shapelib, and hence this module too, defines two types of objects,
+ * shapes and shapefiles.
+ */
+
+%module shapelib
+
+/*
+ * First, a %{,%}-Block. These blocks are copied verbatim to the
+ * shapelib_wrap.c file and are not parsed by SWIG. This is the place to
+ * import headerfiles and define helper-functions that are needed by the
+ * automatically generated wrappers.
+ */
+
+%{
+
+/* import the shapelib headefile. */
+#include "shapefil.h"
+#include "pyshapelib_api.h"
+    
+/*
+ * Rename a few shapelib functions that are effectively methods with
+ * preprocessor macros so that they have the names that swig expects
+ * (e.g. the destructor of SHPObject has to be called delete_SHPObject)
+ */
+
+#define delete_SHPObject SHPDestroyObject
+    
+/*
+ * The extents() method of SHPObject.
+ *
+ * Return the extents as a tuple of two 4-element lists with the min.
+ * and max. values of x, y, z, m.
+ */
+static PyObject *
+SHPObject_extents(SHPObject *object)
+{
+    return Py_BuildValue("[dddd][dddd]",
+			 object->dfXMin, object->dfYMin, object->dfZMin,
+			 object->dfMMin, 
+			 object->dfXMax, object->dfYMax, object->dfZMax,
+			 object->dfMMax);
+}
+
+
+/*
+ * The vertices() method of SHPObject.
+ *
+ * Return the x and y coords of the vertices as a list of lists of
+ * tuples.
+ */
+
+static PyObject* build_vertex_list(SHPObject *object, int index, int length);
+
+static PyObject*
+SHPObject_vertices(SHPObject *object)
+{
+    PyObject *result = NULL;
+    PyObject *part = NULL;
+    int part_idx, vertex_idx;
+    int length = 0;
+
+
+    if (object->nParts > 0)
+    {
+	/* A multipart shape. Usual for SHPT_ARC and SHPT_POLYGON */
+	
+	result = PyList_New(object->nParts);
+	if (!result)
+	    return NULL;
+
+	for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts;
+	     part_idx++)
+	{
+	    if (part_idx < object->nParts - 1)
+		length = (object->panPartStart[part_idx + 1]
+			  - object->panPartStart[part_idx]);
+	    else
+		length = object->nVertices - object->panPartStart[part_idx];
+	    
+	    part = build_vertex_list(object, vertex_idx, length);
+	    if (!part)
+		goto fail;
+
+	    if (PyList_SetItem(result, part_idx, part) < 0)
+		goto fail;
+
+	    vertex_idx += length;
+	}
+    }
+    else
+    {
+	/* only one part. usual for SHPT_POINT */
+	result = build_vertex_list(object, 0, object->nVertices);
+    }
+
+    return result;
+
+ fail:
+    Py_XDECREF(part);
+    Py_DECREF(result);
+    return NULL;
+}
+
+
+/* Return the length coordinates of the shape object starting at vertex
+ * index as a Python-list of tuples. Helper function for
+ * SHPObject_vertices.
+ */
+static PyObject*
+build_vertex_list(SHPObject *object, int index, int length)
+{
+    int i;
+    PyObject * list;
+    PyObject * vertex = NULL;
+
+    list = PyList_New(length);
+    if (!list)
+	return NULL;
+
+    for (i = 0; i < length; i++, index++)
+    {
+	vertex = Py_BuildValue("dd", object->padfX[index],
+			       object->padfY[index]);
+	if (!vertex)
+	    goto fail;
+	if (PyList_SetItem(list, i, vertex) < 0)
+	    goto fail;
+    }
+
+    return list;
+
+ fail:
+    Py_XDECREF(vertex);
+    Py_DECREF(list);
+    return NULL;
+}
+
+
+
+
+
+/* The constructor of SHPObject. parts is a list of lists of tuples
+ * describing the parts and their vertices just likethe output of the
+ * vertices() method. part_type_list is the list of part-types and may
+ * be NULL. For the meaning of the part-types and their default value
+ * see the Shaplib documentation.
+ */
+SHPObject * new_SHPObject(int type, int id, PyObject * parts,
+			  PyObject * part_type_list)
+{
+    /* arrays to hold thex and y coordinates of the  vertices */
+    double *xs = NULL, *ys = NULL;
+    /* number of all vertices of all parts */
+    int num_vertices;
+    /* number of parts in the list parts */
+    int num_parts;
+    /* start index of in xs and ys of the part currently worked on */
+    int part_start;
+    /* array of start indices in xs and ys as expected by shapelib */
+    int *part_starts = NULL;
+
+    /* generic counter */
+    int i;
+
+    /* array of part types. holds the converted content of
+     * part_type_list. Stays NULL of part_type_list is NULL
+     */
+    int *part_types = NULL;
+
+    /* temporary python objects referring to the the list items being
+     * worked on.
+     */
+    PyObject * part = NULL, *tuple = NULL;
+
+    /* The result object */
+    SHPObject *result;
+
+    num_parts = PySequence_Length(parts);
+    num_vertices = 0; 
+
+    /* parts and part_types have to have the same lengths */
+    if (part_type_list
+	&& PySequence_Length(parts) != PySequence_Length(part_type_list))
+    {
+	PyErr_SetString(PyExc_TypeError,
+			"parts and part_types have to have the same lengths");
+	return NULL;
+    }
+
+    /* determine how many vertices there are altogether */
+    for (i = 0; i < num_parts; i++)
+    {
+	PyObject * part = PySequence_GetItem(parts, i);
+	if (!part)
+	    return NULL;
+	num_vertices += PySequence_Length(part);
+	Py_DECREF(part);
+    }
+
+    /* allocate the memory for the various arrays and check for memory
+       errors */
+    xs = malloc(num_vertices * sizeof(double));
+    ys = malloc(num_vertices * sizeof(double));
+    part_starts = malloc(num_parts * sizeof(int));
+    if (part_type_list)
+	part_types = malloc(num_parts * sizeof(int));
+
+    if (!xs || !ys || !part_starts || (part_type_list && !part_types))
+    {
+	PyErr_NoMemory();
+	goto fail;
+    }
+
+    /* convert the part types */
+    if (part_type_list)
+    {
+	for (i = 0; i < num_parts; i++)
+	{
+	    PyObject * otype = PySequence_GetItem(part_type_list, i);
+	    if (!otype)
+		return NULL;
+	    part_types[i] = PyInt_AsLong(otype);
+	    Py_DECREF(otype);
+	}
+    }
+
+    /* convert the list of parts */
+    part_start = 0;
+    for (i = 0; i < num_parts; i++)
+    {
+	int j, length;
+
+	part = PySequence_GetItem(parts, i);
+	length = PySequence_Length(part);
+	part_starts[i] = part_start;
+
+	for (j = 0; j < length; j++)
+	{
+	    tuple = PySequence_GetItem(part, j);
+	    if (!tuple)
+		goto fail;
+
+	    if (!PyArg_ParseTuple(tuple, "dd", xs + part_start + j,
+				  ys + part_start + j))
+	    {
+		goto fail;
+	    }
+	    Py_DECREF(tuple);
+	    tuple = NULL;
+	}
+	Py_DECREF(part);
+	part = NULL;
+	part_start += length;
+    }
+
+    result = SHPCreateObject(type, id, num_parts, part_starts, part_types,
+			     num_vertices, xs, ys, NULL, NULL);
+    free(xs);
+    free(ys);
+    free(part_starts);
+    free(part_types);
+    return result;
+
+ fail:
+    free(xs);
+    free(ys);
+    free(part_starts);
+    free(part_types);
+    Py_XDECREF(part);
+    Py_XDECREF(tuple);
+    return NULL;
+}
+
+%}
+
+
+
+/*
+ * The SWIG Interface definition.
+ */
+
+/* include some common SWIG type definitions and standard exception
+   handling code */
+%include typemaps.i
+%include exception.i
+
+
+/*
+ *  SHPObject -- Represents one shape
+ */
+
+/* Exception typemap for the SHPObject constructor. The constructor the
+   the wrapper function defined above which returns NULL in case of
+   error. */
+   
+%typemap(python,except) SHPObject*new_SHPObject {
+    $function;
+    if (PyErr_Occurred())
+	return NULL;
+}
+
+/* Define the SHPObject struct for SWIG. This has to have the same name
+ * as the underlying C-struct in shapfil.h, but we don't have to repeat
+ * all the fields here, only those we want to access directly, and we
+ * can define methods for the object oriented interface.
+ */
+
+typedef struct {
+
+    /* The shape object has two read-only attributes: */
+
+    /* The type of the shape. In the c-struct defined the field is
+     * called 'nSHPType' but for the python bindings 'type' is more
+     * appropriate.
+     */
+    %readonly %name(type) int nSHPType;
+
+    /* The id of the shape. Here 'id' is a better name than 'nShapeId'. */
+    %readonly %name(id) int nShapeId;
+
+    /* The methods */
+    %addmethods {
+
+	/* the constructor */
+	SHPObject(int type, int id, PyObject * parts,
+		  PyObject * part_types = NULL);
+
+	/* The destructor */
+	~SHPObject();
+
+	/* extents and vertices correspond to the SHPObject_extents and
+	 * SHPObject_vertices defined above
+	 */
+	PyObject *extents();
+	PyObject *vertices();
+    }
+} SHPObject;
+
+
+/*
+ * ShapeFile --  Represents the shape file
+ */
+
+/* Here we do things a little different. We define a new C-struct that
+ * holds the SHPHandle. This is mainly done so we can separate the
+ * close() method from the destructor but it also helps with exception
+ * handling.
+ *
+ * After the ShapeFile has been opened or created the handle is not
+ * NULL. The close() method closes the file and sets handle to NULL as
+ * an indicator that the file has been closed.
+ */
+
+/* First, define the C-struct */
+%{
+    typedef struct {
+	SHPHandle handle;
+    } ShapeFile;
+%}
+
+/* define and use some typemaps for the info() method whose
+ * C-implementation has four output parameters that are returned through
+ * pointers passed into the function. SWIG already has definitions for
+ * common types such as int* and we can use those for the first two
+ * parameters:
+ */
+ 
+%apply int * OUTPUT { int * output_entities }
+%apply int * OUTPUT { int * output_type }
+
+/* for the last two, the 4-element arrays of min- and max-values, we
+ * have to define our own typemaps:
+ */
+%typemap (python,ignore) double * extents(double temp[4]) {
+    $target = temp;
+}
+
+%typemap (python,argout) double * extents {
+    PyObject * list = Py_BuildValue("[dddd]",
+				    $source[0], $source[1],
+				    $source[2], $source[3]);
+    $target = t_output_helper($target,list);
+}
+
+%apply double * extents { double * output_min_bounds }
+%apply double * extents { double * output_max_bounds }
+
+/* The first argument to the ShapeFile methods is a ShapeFile pointer.
+ * We have to check whether handle is not NULL in most methods but not
+ * all. In the destructor and the close method, it's OK for handle to be
+ * NULL. We achieve this by checking whether the preprocessor macro
+ * NOCHECK_$name is defined. SWIG replaces $name with the name of the
+ * function for which the code is inserted. In the %{,%}-block below we
+ * define the macros for the destructor and the close() method.
+ */
+
+
+%typemap(python,check) ShapeFile *{
+    %#ifndef NOCHECK_$name
+    if (!$target || !$target->handle)
+	SWIG_exception(SWIG_TypeError, "shapefile already closed");
+    %#endif
+}
+
+%{
+#define NOCHECK_delete_ShapeFile
+#define NOCHECK_ShapeFile_close
+%}
+
+/* An exception handle for the constructor and the module level open()
+ * and create() functions.
+ *
+ * Annoyingly, we *have* to put braces around the SWIG_exception()
+ * calls, at least in the python case, because of the way the macro is
+ * written. Of course, always putting braces around the branches of an
+ * if-statement is often considered good practice.
+ */
+%typemap(python,except) ShapeFile * {
+    $function;
+    if (!$source)
+    {
+    	SWIG_exception(SWIG_MemoryError, "no memory");
+    }
+    else if (!$source->handle)
+    {
+	SWIG_exception(SWIG_IOError, "$name failed");
+    }
+}
+
+
+/*
+ * The SWIG-version of the ShapeFile struct.
+ */
+
+typedef struct
+{
+    /* Only methods and no attributes here: */ 
+    %addmethods {
+
+	/* The constructor. Takes two arguments, the filename and the
+	 * optinal mode which are passed through to SHPOpen (due to the
+	 * renaming trick)
+	 */
+	ShapeFile(char *file, char * mode = "rb") {
+	    ShapeFile * self = malloc(sizeof(ShapeFile));
+	    if (self)
+		self->handle = SHPOpen(file, mode);
+	    return self;
+	}
+
+	/* The destructor. Equivalent to SHPClose */
+	~ShapeFile() {
+	    if (self->handle)
+		SHPClose(self->handle);
+	    free(self);
+	}
+
+	/* close the shape file and set handle to NULL */
+	void close() {
+	    if (self->handle)
+	    {
+		SHPClose(self->handle);
+		self->handle = NULL;
+	    }
+	}
+
+	/* info() -- Return a tuple (NUM_SHAPES, TYPE, MIN, MAX) where
+	 * NUM_SHAPES is the number of shapes in the file, TYPE is the
+	 * shape type and MIN and MAX are 4-element lists with the min.
+	 * and max. values of the data.
+	 *
+	 * The arguments of the underlying shapelib function SHPGetInfo
+	 * are all output parameters. To tell SWIG this, we have defined
+	 * some typemaps above
+	 */
+	void info(int * output_entities, int * output_type,
+		  double * output_min_bounds, double *output_max_bounds) {
+	    SHPGetInfo(self->handle, output_entities, output_type,
+		       output_min_bounds, output_max_bounds);
+	}
+
+	/* Return object number i */
+	%new SHPObject * read_object(int i) {
+	    return SHPReadObject(self->handle, i);
+	}
+
+	/* Write an object */
+	int write_object(int iShape, SHPObject * psObject) {
+	    return SHPWriteObject(self->handle, iShape, psObject);
+	}
+
+	/* Return the shapelib SHPHandle as a Python CObject */
+	PyObject * cobject() {
+	    return PyCObject_FromVoidPtr(self->handle, NULL);
+	}
+    }
+
+} ShapeFile;
+
+
+/*
+ * Two module level functions, open() and create() that correspond to
+ * SHPOpen and SHPCreate respectively. open() is equivalent to the
+ * ShapeFile constructor.
+ */
+
+%{
+    ShapeFile * open_ShapeFile(const char *filename, const char * mode) {
+	ShapeFile * self = malloc(sizeof(ShapeFile));
+	if (self)
+	    self->handle = SHPOpen(filename, mode);
+	return self;
+    }
+%}
+
+%name(open) %new ShapeFile *open_ShapeFile(const char *filename,
+					   const char * mode = "rb");
+
+
+%{
+    ShapeFile * create_ShapeFile(const char *filename, int type) {
+	ShapeFile * self = malloc(sizeof(ShapeFile));
+	if (self)
+	    self->handle = SHPCreate(filename, type);
+	return self;
+    }
+%}    
+
+%name(create) %new ShapeFile * create_ShapeFile(const char *filename,
+						int type);
+    
+
+/* Module level function to expose some of the shapelib functions linked
+ * with the shapefile C-module to other Python extension modules. This
+ * is a kludge to make a Thuban extension work that reads shapes from
+ * shapefiles opened by the shapefile module.
+ */
+
+%{
+    static PyShapeLibAPI the_api = {
+	SHPReadObject,
+	SHPDestroyObject,
+	SHPCreateTree,
+	SHPDestroyTree,
+	SHPTreeFindLikelyShapes
+    };
+
+    PyObject * c_api() {
+	return PyCObject_FromVoidPtr(&the_api, NULL);
+    }
+%}
+
+PyObject * c_api();
+
+
+/*
+ *  Module Level functions 
+ */
+
+/* convert shapefile types to names */
+%name(type_name) const char *SHPTypeName(int nSHPType);
+%name(part_type_name) const char *SHPPartTypeName(int nPartType);
+
+
+/*
+ * Finally, constants copied from shapefil.h
+ */
+
+/* -------------------------------------------------------------------- */
+/*      Shape types (nSHPType)                                          */
+/* -------------------------------------------------------------------- */
+#define SHPT_NULL	0
+#define SHPT_POINT	1
+#define SHPT_ARC	3
+#define SHPT_POLYGON	5
+#define SHPT_MULTIPOINT	8
+#define SHPT_POINTZ	11
+#define SHPT_ARCZ	13
+#define SHPT_POLYGONZ	15
+#define SHPT_MULTIPOINTZ 18
+#define SHPT_POINTM	21
+#define SHPT_ARCM	23
+#define SHPT_POLYGONM	25
+#define SHPT_MULTIPOINTM 28
+#define SHPT_MULTIPATCH 31
+
+
+/* -------------------------------------------------------------------- */
+/*      Part types - everything but SHPT_MULTIPATCH just uses           */
+/*      SHPP_RING.                                                      */
+/* -------------------------------------------------------------------- */
+
+#define SHPP_TRISTRIP	0
+#define SHPP_TRIFAN	1
+#define SHPP_OUTERRING	2
+#define SHPP_INNERRING	3
+#define SHPP_FIRSTRING	4
+#define SHPP_RING	5
+
+

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib.py
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,119 @@
+# This file was created automatically by SWIG.
+import shapelibc
+class SHPObject:
+    def __init__(self,*args):
+        self.this = apply(shapelibc.new_SHPObject,args)
+        self.thisown = 1
+
+    def __del__(self,shapelibc=shapelibc):
+        if self.thisown == 1 :
+            shapelibc.delete_SHPObject(self)
+    def extents(*args):
+        val = apply(shapelibc.SHPObject_extents,args)
+        return val
+    def vertices(*args):
+        val = apply(shapelibc.SHPObject_vertices,args)
+        return val
+    __setmethods__ = {
+    }
+    def __setattr__(self,name,value):
+        if (name == "this") or (name == "thisown"): self.__dict__[name] = value; return
+        method = SHPObject.__setmethods__.get(name,None)
+        if method: return method(self,value)
+        self.__dict__[name] = value
+    __getmethods__ = {
+        "type" : shapelibc.SHPObject_type_get,
+        "id" : shapelibc.SHPObject_id_get,
+    }
+    def __getattr__(self,name):
+        method = SHPObject.__getmethods__.get(name,None)
+        if method: return method(self)
+        raise AttributeError,name
+    def __repr__(self):
+        return "<C SHPObject instance at %s>" % (self.this,)
+class SHPObjectPtr(SHPObject):
+    def __init__(self,this):
+        self.this = this
+        self.thisown = 0
+        self.__class__ = SHPObject
+
+
+
+class ShapeFile:
+    def __init__(self,*args):
+        self.this = apply(shapelibc.new_ShapeFile,args)
+        self.thisown = 1
+
+    def __del__(self,shapelibc=shapelibc):
+        if self.thisown == 1 :
+            shapelibc.delete_ShapeFile(self)
+    def close(*args):
+        val = apply(shapelibc.ShapeFile_close,args)
+        return val
+    def info(*args):
+        val = apply(shapelibc.ShapeFile_info,args)
+        return val
+    def read_object(*args):
+        val = apply(shapelibc.ShapeFile_read_object,args)
+        if val: val = SHPObjectPtr(val) ; val.thisown = 1
+        return val
+    def write_object(*args):
+        val = apply(shapelibc.ShapeFile_write_object,args)
+        return val
+    def cobject(*args):
+        val = apply(shapelibc.ShapeFile_cobject,args)
+        return val
+    def __repr__(self):
+        return "<C ShapeFile instance at %s>" % (self.this,)
+class ShapeFilePtr(ShapeFile):
+    def __init__(self,this):
+        self.this = this
+        self.thisown = 0
+        self.__class__ = ShapeFile
+
+
+
+
+
+#-------------- FUNCTION WRAPPERS ------------------
+
+def open(*args, **kwargs):
+    val = apply(shapelibc.open,args,kwargs)
+    if val: val = ShapeFilePtr(val); val.thisown = 1
+    return val
+
+def create(*args, **kwargs):
+    val = apply(shapelibc.create,args,kwargs)
+    if val: val = ShapeFilePtr(val); val.thisown = 1
+    return val
+
+c_api = shapelibc.c_api
+
+type_name = shapelibc.type_name
+
+part_type_name = shapelibc.part_type_name
+
+
+
+#-------------- VARIABLE WRAPPERS ------------------
+
+SHPT_NULL = shapelibc.SHPT_NULL
+SHPT_POINT = shapelibc.SHPT_POINT
+SHPT_ARC = shapelibc.SHPT_ARC
+SHPT_POLYGON = shapelibc.SHPT_POLYGON
+SHPT_MULTIPOINT = shapelibc.SHPT_MULTIPOINT
+SHPT_POINTZ = shapelibc.SHPT_POINTZ
+SHPT_ARCZ = shapelibc.SHPT_ARCZ
+SHPT_POLYGONZ = shapelibc.SHPT_POLYGONZ
+SHPT_MULTIPOINTZ = shapelibc.SHPT_MULTIPOINTZ
+SHPT_POINTM = shapelibc.SHPT_POINTM
+SHPT_ARCM = shapelibc.SHPT_ARCM
+SHPT_POLYGONM = shapelibc.SHPT_POLYGONM
+SHPT_MULTIPOINTM = shapelibc.SHPT_MULTIPOINTM
+SHPT_MULTIPATCH = shapelibc.SHPT_MULTIPATCH
+SHPP_TRISTRIP = shapelibc.SHPP_TRISTRIP
+SHPP_TRIFAN = shapelibc.SHPP_TRIFAN
+SHPP_OUTERRING = shapelibc.SHPP_OUTERRING
+SHPP_INNERRING = shapelibc.SHPP_INNERRING
+SHPP_FIRSTRING = shapelibc.SHPP_FIRSTRING
+SHPP_RING = shapelibc.SHPP_RING

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib_wrap.c
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib_wrap.c	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/shapelib_wrap.c	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1411 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3u-20050630-1524 (Alpha 5)
+ * 
+ * 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
+ * changes to this file unless you know what you are doing--modify the SWIG 
+ * interface file instead. 
+ * ----------------------------------------------------------------------------- */
+
+#define SWIGPYTHON
+/***********************************************************************
+ * common.swg
+ *
+ *     This file contains generic SWIG runtime support for pointer
+ *     type checking as well as a few commonly used macros to control
+ *     external linkage.
+ *
+ * Author : David Beazley (beazley at cs.uchicago.edu)
+ *
+ * Copyright (c) 1999-2000, The University of Chicago
+ * 
+ * This file may be freely redistributed without license or fee provided
+ * this copyright message remains intact.
+ ************************************************************************/
+
+#include <string.h>
+
+#if defined(_WIN32) || defined(__WIN32__)
+#       if defined(_MSC_VER)
+#               if defined(STATIC_LINKED)
+#                       define SWIGEXPORT(a) a
+#               else
+#                       define SWIGEXPORT(a) __declspec(dllexport) a
+#               endif
+#       else
+#               if defined(__BORLANDC__)
+#                       define SWIGEXPORT(a) a _export
+#               else
+#                       define SWIGEXPORT(a) a
+#       endif
+#endif
+#else
+#       define SWIGEXPORT(a) a
+#endif
+
+#ifdef SWIG_GLOBAL
+#define SWIGRUNTIME(a) SWIGEXPORT(a)
+#else
+#define SWIGRUNTIME(a) static a
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct swig_type_info {
+  char  *name;                 
+  void *(*converter)(void *);
+  char  *str;
+  struct swig_type_info  *next;
+  struct swig_type_info  *prev;
+} swig_type_info;
+
+#ifdef SWIG_NOINCLUDE
+SWIGEXPORT(swig_type_info *) SWIG_TypeRegister(swig_type_info *);
+SWIGEXPORT(swig_type_info *) SWIG_TypeCheck(char *c, swig_type_info *);
+SWIGEXPORT(void *) SWIG_TypeCast(swig_type_info *, void *);
+#else
+
+static swig_type_info *swig_type_list = 0;
+
+/* Register a type mapping with the type-checking */
+SWIGRUNTIME(swig_type_info *)
+SWIG_TypeRegister(swig_type_info *ti)
+{
+  swig_type_info *tc, *head, *ret, *next;
+  /* Check to see if this type has already been registered */
+  tc = swig_type_list;
+  while (tc) {
+    if (strcmp(tc->name, ti->name) == 0) {
+      /* Already exists in the table.  Just add additional types to the list */
+      head = tc;
+      next = tc->next;
+      goto l1;
+    }
+    tc = tc->prev;
+  }
+  head = ti;
+  next = 0;
+
+  /* Place in list */
+  ti->prev = swig_type_list;
+  swig_type_list = ti;
+
+  /* Build linked lists */
+ l1:
+  ret = head;
+  tc = ti + 1;
+  /* Patch up the rest of the links */
+  while (tc->name) {
+    head->next = tc;
+    tc->prev = head;
+    head = tc;
+    tc++;
+  }
+  head->next = next;
+  return ret;
+}
+
+/* Check the typename */
+SWIGRUNTIME(swig_type_info *) 
+SWIG_TypeCheck(char *c, swig_type_info *ty)
+{
+  swig_type_info *s;
+  if (!ty) return 0;        /* Void pointer */
+  s = ty->next;             /* First element always just a name */
+  while (s) {
+    if (strcmp(s->name,c) == 0) {
+      if (s == ty->next) return s;
+      /* Move s to the top of the linked list */
+      s->prev->next = s->next;
+      if (s->next) {
+	s->next->prev = s->prev;
+      }
+      /* Insert s as second element in the list */
+      s->next = ty->next;
+      if (ty->next) ty->next->prev = s;
+      ty->next = s;
+      return s;
+    }
+    s = s->next;
+  }
+  return 0;
+}
+
+/* Cast a pointer (needed for C++ inheritance */
+SWIGRUNTIME(void *) 
+SWIG_TypeCast(swig_type_info *ty, void *ptr) 
+{
+  if ((!ty) || (!ty->converter)) return ptr;
+  return (*ty->converter)(ptr);
+}
+
+/* Search for a swig_type_info structure */
+SWIGRUNTIME(void *)
+SWIG_TypeQuery(const char *name) {
+  swig_type_info *ty = swig_type_list;
+  while (ty) {
+    if (ty->str && (strcmp(name,ty->str) == 0)) return ty;
+    if (ty->name && (strcmp(name,ty->name) == 0)) return ty;
+    ty = ty->prev;
+  }
+  return 0;
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+/***********************************************************************
+ * python.swg
+ *
+ *     This file contains the runtime support for Python modules
+ *     and includes code for managing global variables and pointer
+ *     type checking.
+ *
+ * Author : David Beazley (beazley at cs.uchicago.edu)
+ ************************************************************************/
+
+#include <stdlib.h>
+#include "Python.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SWIG_PY_INT     1
+#define SWIG_PY_FLOAT   2
+#define SWIG_PY_STRING  3
+#define SWIG_PY_POINTER 4
+
+/* Constant information structure */
+typedef struct swig_const_info {
+    int type;
+    char *name;
+    long lvalue;
+    double dvalue;
+    void   *pvalue;
+    swig_type_info **ptype;
+} swig_const_info;
+
+#ifdef SWIG_NOINCLUDE
+
+SWIGEXPORT(PyObject *)        SWIG_newvarlink();
+SWIGEXPORT(void)              SWIG_addvarlink(PyObject *, char *, PyObject *(*)(void), int (*)(PyObject *));
+SWIGEXPORT(int)               SWIG_ConvertPtr(PyObject *, void **, swig_type_info *, int);
+SWIGEXPORT(void)              SWIG_MakePtr(char *c, void *, swig_type_info *);
+SWIGEXPORT(PyObject *)        SWIG_NewPointerObj(void *, swig_type_info *);
+SWIGEXPORT(void)              SWIG_InstallConstants(PyObject *d, swig_const_info constants[]);
+
+#else
+
+/* -----------------------------------------------------------------------------
+ * global variable support code.
+ * ----------------------------------------------------------------------------- */
+
+typedef struct swig_globalvar {   
+  char       *name;                  /* Name of global variable */
+  PyObject *(*get_attr)(void);       /* Return the current value */
+  int       (*set_attr)(PyObject *); /* Set the value */
+  struct swig_globalvar *next;
+} swig_globalvar;
+
+typedef struct swig_varlinkobject {
+  PyObject_HEAD
+  swig_globalvar *vars;
+} swig_varlinkobject;
+
+static PyObject *
+swig_varlink_repr(swig_varlinkobject *v) {
+  v = v;
+  return PyString_FromString("<Global variables>");
+}
+
+static int
+swig_varlink_print(swig_varlinkobject *v, FILE *fp, int flags) {
+  swig_globalvar  *var;
+  flags = flags;
+  fprintf(fp,"Global variables { ");
+  for (var = v->vars; var; var=var->next) {
+    fprintf(fp,"%s", var->name);
+    if (var->next) fprintf(fp,", ");
+  }
+  fprintf(fp," }\n");
+  return 0;
+}
+
+static PyObject *
+swig_varlink_getattr(swig_varlinkobject *v, char *n) {
+  swig_globalvar *var = v->vars;
+  while (var) {
+    if (strcmp(var->name,n) == 0) {
+      return (*var->get_attr)();
+    }
+    var = var->next;
+  }
+  PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+  return NULL;
+}
+
+static int
+swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) {
+  swig_globalvar *var = v->vars;
+  while (var) {
+    if (strcmp(var->name,n) == 0) {
+      return (*var->set_attr)(p);
+    }
+    var = var->next;
+  }
+  PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+  return 1;
+}
+
+statichere PyTypeObject varlinktype = {
+  PyObject_HEAD_INIT(0)              
+  0,
+  "swigvarlink",                      /* Type name    */
+  sizeof(swig_varlinkobject),         /* Basic size   */
+  0,                                  /* Itemsize     */
+  0,                                  /* Deallocator  */ 
+  (printfunc) swig_varlink_print,     /* Print        */
+  (getattrfunc) swig_varlink_getattr, /* get attr     */
+  (setattrfunc) swig_varlink_setattr, /* Set attr     */
+  0,                                  /* tp_compare   */
+  (reprfunc) swig_varlink_repr,       /* tp_repr      */    
+  0,                                  /* tp_as_number */
+  0,                                  /* tp_as_mapping*/
+  0,                                  /* tp_hash      */
+};
+
+/* Create a variable linking object for use later */
+SWIGRUNTIME(PyObject *)
+SWIG_newvarlink(void) {
+  swig_varlinkobject *result = 0;
+  result = PyMem_NEW(swig_varlinkobject,1);
+  varlinktype.ob_type = &PyType_Type;    /* Patch varlinktype into a PyType */
+  result->ob_type = &varlinktype;
+  result->vars = 0;
+  result->ob_refcnt = 0;
+  Py_XINCREF((PyObject *) result);
+  return ((PyObject*) result);
+}
+
+SWIGRUNTIME(void)
+SWIG_addvarlink(PyObject *p, char *name,
+	   PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) {
+  swig_varlinkobject *v;
+  swig_globalvar *gv;
+  v= (swig_varlinkobject *) p;
+  gv = (swig_globalvar *) malloc(sizeof(swig_globalvar));
+  gv->name = (char *) malloc(strlen(name)+1);
+  strcpy(gv->name,name);
+  gv->get_attr = get_attr;
+  gv->set_attr = set_attr;
+  gv->next = v->vars;
+  v->vars = gv;
+}
+/* Convert a pointer value */
+SWIGRUNTIME(int)
+SWIG_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) {
+  unsigned long p;
+  register int d;
+  swig_type_info *tc;
+  char  *c;
+  static PyObject *SWIG_this = 0;
+  int    newref = 0;
+
+  if (!obj || (obj == Py_None)) {
+    *ptr = 0;
+    return 0;
+  }
+#ifdef SWIG_COBJECT_TYPES
+  if (!(PyCObject_Check(obj))) {
+    if (!SWIG_this)
+      SWIG_this = PyString_InternFromString("this");
+    obj = PyObject_GetAttr(obj,SWIG_this);
+    newref = 1;
+    if (!obj) goto type_error;
+    if (!PyCObject_Check(obj)) {
+      Py_DECREF(obj);
+      goto type_error;
+    }
+  } 
+  *ptr = PyCObject_AsVoidPtr(obj);
+  c = (char *) PyCObject_GetDesc(obj);
+  if (newref) Py_DECREF(obj);
+  goto cobject;
+#else
+  if (!(PyString_Check(obj))) {
+    if (!SWIG_this)
+      SWIG_this = PyString_InternFromString("this");
+    obj = PyObject_GetAttr(obj,SWIG_this);
+    newref = 1;
+    if (!obj) goto type_error;
+    if (!PyString_Check(obj)) {
+      Py_DECREF(obj);
+      goto type_error;
+    }
+  } 
+  c = PyString_AsString(obj);
+  p = 0;
+  /* Pointer values must start with leading underscore */
+  if (*c != '_') {
+    *ptr = (void *) 0;
+    if (strcmp(c,"NULL") == 0) {
+      if (newref) Py_DECREF(obj);
+      return 0;
+    } else {
+      if (newref) Py_DECREF(obj);
+      goto type_error;
+    }
+  }
+  c++;
+  /* Extract hex value from pointer */
+  while ((d = *c)) {
+    if ((d >= '0') && (d <= '9'))
+      p = (p << 4) + (d - '0');
+    else if ((d >= 'a') && (d <= 'f'))
+      p = (p << 4) + (d - ('a'-10));
+    else
+      break; 
+    c++;
+  }
+  *ptr = (void *) p;
+  if (newref) Py_DECREF(obj);
+#endif
+
+#ifdef SWIG_COBJECT_TYPES
+cobject:
+#endif
+
+  if (ty) {
+    tc = SWIG_TypeCheck(c,ty);
+    if (!tc) goto type_error;
+    *ptr = SWIG_TypeCast(tc,(void*)p);
+  }
+  return 0;
+
+type_error:
+
+  if (flags) {
+    if (ty) {
+      char *temp = (char *) malloc(64+strlen(ty->name));
+      sprintf(temp,"Type error. Expected %s", ty->name);
+      PyErr_SetString(PyExc_TypeError, temp);
+      free((char *) temp);
+    } else {
+      PyErr_SetString(PyExc_TypeError,"Expected a pointer");
+    }
+  }
+  return -1;
+}
+
+/* Take a pointer and convert it to a string */
+SWIGRUNTIME(void) 
+SWIG_MakePtr(char *c, void *ptr, swig_type_info *ty) {
+  static char hex[17] = "0123456789abcdef";
+  unsigned long p, s;
+  char result[32], *r; 
+  r = result;
+  p = (unsigned long) ptr;
+  if (p > 0) {
+    while (p > 0) {
+      s = p & 0xf;
+      *(r++) = hex[s];
+      p = p >> 4;
+    }
+    *r = '_';
+    while (r >= result)
+      *(c++) = *(r--);
+    strcpy (c, ty->name);
+  } else {
+    strcpy (c, "NULL");
+  }
+}
+
+/* Create a new pointer object */
+SWIGRUNTIME(PyObject *)
+SWIG_NewPointerObj(void *ptr, swig_type_info *type) {
+  char result[512];
+  PyObject *robj;
+  if (!ptr) {
+    Py_INCREF(Py_None);
+    return Py_None;
+  }
+#ifdef SWIG_COBJECT_TYPES
+  robj = PyCObject_FromVoidPtrAndDesc((void *) ptr, type->name, NULL);
+#else
+  SWIG_MakePtr(result,ptr,type);
+  robj = PyString_FromString(result);
+#endif
+  return robj;
+}
+
+/* Install Constants */
+SWIGRUNTIME(void)
+SWIG_InstallConstants(PyObject *d, swig_const_info constants[]) {
+  int i;
+  PyObject *obj;
+  for (i = 0; constants[i].type; i++) {
+    switch(constants[i].type) {
+    case SWIG_PY_INT:
+      obj = PyInt_FromLong(constants[i].lvalue);
+      break;
+    case SWIG_PY_FLOAT:
+      obj = PyFloat_FromDouble(constants[i].dvalue);
+      break;
+    case SWIG_PY_STRING:
+      obj = PyString_FromString((char *) constants[i].pvalue);
+      break;
+    case SWIG_PY_POINTER:
+      obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype);
+      break;
+    default:
+      obj = 0;
+      break;
+    }
+    if (obj) {
+      PyDict_SetItemString(d,constants[i].name,obj);
+      Py_DECREF(obj);
+    }
+  }
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+/* -------- TYPES TABLE (BEGIN) -------- */
+
+#define  SWIGTYPE_p_ShapeFile swig_types[0] 
+#define  SWIGTYPE_p_SHPObject swig_types[1] 
+static swig_type_info *swig_types[3];
+
+/* -------- TYPES TABLE (END) -------- */
+
+
+/*-----------------------------------------------
+              @(target):= shapelibc.so
+  ------------------------------------------------*/
+#define SWIG_init    initshapelibc
+
+#define SWIG_name    "shapelibc"
+
+
+/* import the shapelib headefile. */
+#include "shapefil.h"
+#include "pyshapelib_api.h"
+    
+/*
+ * Rename a few shapelib functions that are effectively methods with
+ * preprocessor macros so that they have the names that swig expects
+ * (e.g. the destructor of SHPObject has to be called delete_SHPObject)
+ */
+
+#define delete_SHPObject SHPDestroyObject
+    
+/*
+ * The extents() method of SHPObject.
+ *
+ * Return the extents as a tuple of two 4-element lists with the min.
+ * and max. values of x, y, z, m.
+ */
+static PyObject *
+SHPObject_extents(SHPObject *object)
+{
+    return Py_BuildValue("[dddd][dddd]",
+			 object->dfXMin, object->dfYMin, object->dfZMin,
+			 object->dfMMin, 
+			 object->dfXMax, object->dfYMax, object->dfZMax,
+			 object->dfMMax);
+}
+
+
+/*
+ * The vertices() method of SHPObject.
+ *
+ * Return the x and y coords of the vertices as a list of lists of
+ * tuples.
+ */
+
+static PyObject* build_vertex_list(SHPObject *object, int index, int length);
+
+static PyObject*
+SHPObject_vertices(SHPObject *object)
+{
+    PyObject *result = NULL;
+    PyObject *part = NULL;
+    int part_idx, vertex_idx;
+    int length = 0;
+
+
+    if (object->nParts > 0)
+    {
+	/* A multipart shape. Usual for SHPT_ARC and SHPT_POLYGON */
+	
+	result = PyList_New(object->nParts);
+	if (!result)
+	    return NULL;
+
+	for (part_idx = 0, vertex_idx = 0; part_idx < object->nParts;
+	     part_idx++)
+	{
+	    if (part_idx < object->nParts - 1)
+		length = (object->panPartStart[part_idx + 1]
+			  - object->panPartStart[part_idx]);
+	    else
+		length = object->nVertices - object->panPartStart[part_idx];
+	    
+	    part = build_vertex_list(object, vertex_idx, length);
+	    if (!part)
+		goto fail;
+
+	    if (PyList_SetItem(result, part_idx, part) < 0)
+		goto fail;
+
+	    vertex_idx += length;
+	}
+    }
+    else
+    {
+	/* only one part. usual for SHPT_POINT */
+	result = build_vertex_list(object, 0, object->nVertices);
+    }
+
+    return result;
+
+ fail:
+    Py_XDECREF(part);
+    Py_DECREF(result);
+    return NULL;
+}
+
+
+/* Return the length coordinates of the shape object starting at vertex
+ * index as a Python-list of tuples. Helper function for
+ * SHPObject_vertices.
+ */
+static PyObject*
+build_vertex_list(SHPObject *object, int index, int length)
+{
+    int i;
+    PyObject * list;
+    PyObject * vertex = NULL;
+
+    list = PyList_New(length);
+    if (!list)
+	return NULL;
+
+    for (i = 0; i < length; i++, index++)
+    {
+	vertex = Py_BuildValue("dd", object->padfX[index],
+			       object->padfY[index]);
+	if (!vertex)
+	    goto fail;
+	if (PyList_SetItem(list, i, vertex) < 0)
+	    goto fail;
+    }
+
+    return list;
+
+ fail:
+    Py_XDECREF(vertex);
+    Py_DECREF(list);
+    return NULL;
+}
+
+
+
+
+
+/* The constructor of SHPObject. parts is a list of lists of tuples
+ * describing the parts and their vertices just likethe output of the
+ * vertices() method. part_type_list is the list of part-types and may
+ * be NULL. For the meaning of the part-types and their default value
+ * see the Shaplib documentation.
+ */
+SHPObject * new_SHPObject(int type, int id, PyObject * parts,
+			  PyObject * part_type_list)
+{
+    /* arrays to hold thex and y coordinates of the  vertices */
+    double *xs = NULL, *ys = NULL;
+    /* number of all vertices of all parts */
+    int num_vertices;
+    /* number of parts in the list parts */
+    int num_parts;
+    /* start index of in xs and ys of the part currently worked on */
+    int part_start;
+    /* array of start indices in xs and ys as expected by shapelib */
+    int *part_starts = NULL;
+
+    /* generic counter */
+    int i;
+
+    /* array of part types. holds the converted content of
+     * part_type_list. Stays NULL of part_type_list is NULL
+     */
+    int *part_types = NULL;
+
+    /* temporary python objects referring to the the list items being
+     * worked on.
+     */
+    PyObject * part = NULL, *tuple = NULL;
+
+    /* The result object */
+    SHPObject *result;
+
+    num_parts = PySequence_Length(parts);
+    num_vertices = 0; 
+
+    /* parts and part_types have to have the same lengths */
+    if (part_type_list
+	&& PySequence_Length(parts) != PySequence_Length(part_type_list))
+    {
+	PyErr_SetString(PyExc_TypeError,
+			"parts and part_types have to have the same lengths");
+	return NULL;
+    }
+
+    /* determine how many vertices there are altogether */
+    for (i = 0; i < num_parts; i++)
+    {
+	PyObject * part = PySequence_GetItem(parts, i);
+	if (!part)
+	    return NULL;
+	num_vertices += PySequence_Length(part);
+	Py_DECREF(part);
+    }
+
+    /* allocate the memory for the various arrays and check for memory
+       errors */
+    xs = malloc(num_vertices * sizeof(double));
+    ys = malloc(num_vertices * sizeof(double));
+    part_starts = malloc(num_parts * sizeof(int));
+    if (part_type_list)
+	part_types = malloc(num_parts * sizeof(int));
+
+    if (!xs || !ys || !part_starts || (part_type_list && !part_types))
+    {
+	PyErr_NoMemory();
+	goto fail;
+    }
+
+    /* convert the part types */
+    if (part_type_list)
+    {
+	for (i = 0; i < num_parts; i++)
+	{
+	    PyObject * otype = PySequence_GetItem(part_type_list, i);
+	    if (!otype)
+		return NULL;
+	    part_types[i] = PyInt_AsLong(otype);
+	    Py_DECREF(otype);
+	}
+    }
+
+    /* convert the list of parts */
+    part_start = 0;
+    for (i = 0; i < num_parts; i++)
+    {
+	int j, length;
+
+	part = PySequence_GetItem(parts, i);
+	length = PySequence_Length(part);
+	part_starts[i] = part_start;
+
+	for (j = 0; j < length; j++)
+	{
+	    tuple = PySequence_GetItem(part, j);
+	    if (!tuple)
+		goto fail;
+
+	    if (!PyArg_ParseTuple(tuple, "dd", xs + part_start + j,
+				  ys + part_start + j))
+	    {
+		goto fail;
+	    }
+	    Py_DECREF(tuple);
+	    tuple = NULL;
+	}
+	Py_DECREF(part);
+	part = NULL;
+	part_start += length;
+    }
+
+    result = SHPCreateObject(type, id, num_parts, part_starts, part_types,
+			     num_vertices, xs, ys, NULL, NULL);
+    free(xs);
+    free(ys);
+    free(part_starts);
+    free(part_types);
+    return result;
+
+ fail:
+    free(xs);
+    free(ys);
+    free(part_starts);
+    free(part_types);
+    Py_XDECREF(part);
+    Py_XDECREF(tuple);
+    return NULL;
+}
+
+
+static PyObject* l_output_helper(PyObject* target, PyObject* o) {
+    PyObject*   o2;
+    if (!target) {                   
+        target = o;
+    } else if (target == Py_None) {  
+        Py_DECREF(Py_None);
+        target = o;
+    } else {                         
+        if (!PyList_Check(target)) {
+            o2 = target;
+            target = PyList_New(0);
+            PyList_Append(target, o2);
+	    Py_XDECREF(o2);
+        }
+        PyList_Append(target,o);
+	Py_XDECREF(o);
+    }
+    return target;
+}
+
+static PyObject* t_output_helper(PyObject* target, PyObject* o) {
+    PyObject*   o2;
+    PyObject*   o3;
+
+    if (!target) {                   
+        target = o;
+    } else if (target == Py_None) {  
+        Py_DECREF(Py_None);
+        target = o;
+    } else {                         
+        if (!PyTuple_Check(target)) {
+            o2 = target;
+            target = PyTuple_New(1);
+            PyTuple_SetItem(target, 0, o2);
+        }
+        o3 = PyTuple_New(1);            
+        PyTuple_SetItem(o3, 0, o);      
+
+        o2 = target;
+        target = PySequence_Concat(o2, o3); 
+        Py_DECREF(o2);                      
+        Py_DECREF(o3);
+    }
+    return target;
+}
+
+#define  SWIG_MemoryError    1
+#define  SWIG_IOError        2
+#define  SWIG_RuntimeError   3
+#define  SWIG_IndexError     4
+#define  SWIG_TypeError      5
+#define  SWIG_DivisionByZero 6
+#define  SWIG_OverflowError  7
+#define  SWIG_SyntaxError    8
+#define  SWIG_ValueError     9
+#define  SWIG_SystemError   10
+#define  SWIG_UnknownError  99
+
+static void _SWIG_exception(int code, char *msg) {
+  switch(code) {
+  case SWIG_MemoryError:
+    PyErr_SetString(PyExc_MemoryError,msg);
+    break;
+  case SWIG_IOError:
+    PyErr_SetString(PyExc_IOError,msg);
+    break;
+  case SWIG_RuntimeError:
+    PyErr_SetString(PyExc_RuntimeError,msg);
+    break;
+  case SWIG_IndexError:
+    PyErr_SetString(PyExc_IndexError,msg);
+    break;
+  case SWIG_TypeError:
+    PyErr_SetString(PyExc_TypeError,msg);
+    break;
+  case SWIG_DivisionByZero:
+    PyErr_SetString(PyExc_ZeroDivisionError,msg);
+    break;
+  case SWIG_OverflowError:
+    PyErr_SetString(PyExc_OverflowError,msg);
+    break;
+  case SWIG_SyntaxError:
+    PyErr_SetString(PyExc_SyntaxError,msg);
+    break;
+  case SWIG_ValueError:
+    PyErr_SetString(PyExc_ValueError,msg);
+    break;
+  case SWIG_SystemError:
+    PyErr_SetString(PyExc_SystemError,msg);
+    break;
+  default:
+    PyErr_SetString(PyExc_RuntimeError,msg);
+    break;
+  }
+}
+
+#define SWIG_exception(a,b) { _SWIG_exception(a,b); return NULL; }
+
+    typedef struct {
+	SHPHandle handle;
+    } ShapeFile;
+
+#define NOCHECK_delete_ShapeFile
+#define NOCHECK_ShapeFile_close
+
+    ShapeFile * open_ShapeFile(const char *filename, const char * mode) {
+	ShapeFile * self = malloc(sizeof(ShapeFile));
+	if (self)
+	    self->handle = SHPOpen(filename, mode);
+	return self;
+    }
+
+    ShapeFile * create_ShapeFile(const char *filename, int type) {
+	ShapeFile * self = malloc(sizeof(ShapeFile));
+	if (self)
+	    self->handle = SHPCreate(filename, type);
+	return self;
+    }
+
+    static PyShapeLibAPI the_api = {
+	SHPReadObject,
+	SHPDestroyObject,
+	SHPCreateTree,
+	SHPDestroyTree,
+	SHPTreeFindLikelyShapes
+    };
+
+    PyObject * c_api() {
+	return PyCObject_FromVoidPtr(&the_api, NULL);
+    }
+#ifdef __cplusplus
+extern "C" {
+#endif
+static PyObject *_wrap_open(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    char *arg0 ;
+    char *arg1 = "rb" ;
+    ShapeFile *result ;
+    
+    if(!PyArg_ParseTuple(args,"s|s:open",&arg0,&arg1)) return NULL;
+    {
+        result = (ShapeFile *)open_ShapeFile((char const *)arg0,(char const *)arg1);
+        ;
+        if (!result)
+        {
+            SWIG_exception(SWIG_MemoryError, "no memory");
+        }
+        else if (!result->handle)
+        {
+            SWIG_exception(SWIG_IOError, "open_ShapeFile failed");
+        }
+    }resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_ShapeFile);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_create(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    char *arg0 ;
+    int arg1 ;
+    ShapeFile *result ;
+    
+    if(!PyArg_ParseTuple(args,"si:create",&arg0,&arg1)) return NULL;
+    {
+        result = (ShapeFile *)create_ShapeFile((char const *)arg0,arg1);
+        ;
+        if (!result)
+        {
+            SWIG_exception(SWIG_MemoryError, "no memory");
+        }
+        else if (!result->handle)
+        {
+            SWIG_exception(SWIG_IOError, "create_ShapeFile failed");
+        }
+    }resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_ShapeFile);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_c_api(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    PyObject *result ;
+    
+    if(!PyArg_ParseTuple(args,":c_api")) return NULL;
+    result = (PyObject *)c_api();
+    {
+        resultobj = result;
+    }
+    return resultobj;
+}
+
+
+static PyObject *_wrap_type_name(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    int arg0 ;
+    char *result ;
+    
+    if(!PyArg_ParseTuple(args,"i:type_name",&arg0)) return NULL;
+    result = (char *)SHPTypeName(arg0);
+    resultobj = PyString_FromString(result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_part_type_name(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    int arg0 ;
+    char *result ;
+    
+    if(!PyArg_ParseTuple(args,"i:part_type_name",&arg0)) return NULL;
+    result = (char *)SHPPartTypeName(arg0);
+    resultobj = PyString_FromString(result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_SHPObject_type_get(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    SHPObject *arg0 ;
+    PyObject * argo0 =0 ;
+    int result ;
+    
+    if(!PyArg_ParseTuple(args,"O:SHPObject_type_get",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_SHPObject,1)) == -1) return NULL;
+    result = (int ) (arg0->nSHPType);
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_SHPObject_id_get(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    SHPObject *arg0 ;
+    PyObject * argo0 =0 ;
+    int result ;
+    
+    if(!PyArg_ParseTuple(args,"O:SHPObject_id_get",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_SHPObject,1)) == -1) return NULL;
+    result = (int ) (arg0->nShapeId);
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_new_SHPObject(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    int arg0 ;
+    int arg1 ;
+    PyObject *arg2 ;
+    PyObject *arg3 = NULL ;
+    PyObject * obj2  = 0 ;
+    PyObject * obj3  = 0 ;
+    SHPObject *result ;
+    
+    if(!PyArg_ParseTuple(args,"iiO|O:new_SHPObject",&arg0,&arg1,&obj2,&obj3)) return NULL;
+    {
+        arg2 = obj2;
+    }
+    if (obj3)
+    {
+        arg3 = obj3;
+    }
+    {
+        result = (SHPObject *)new_SHPObject(arg0,arg1,arg2,arg3);
+        ;
+        if (PyErr_Occurred())
+        return NULL;
+    }resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_SHPObject);
+    return resultobj;
+}
+
+
+static PyObject *_wrap_delete_SHPObject(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    SHPObject *arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:delete_SHPObject",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_SHPObject,1)) == -1) return NULL;
+    delete_SHPObject(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+static PyObject *_wrap_SHPObject_extents(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    SHPObject *arg0 ;
+    PyObject * argo0 =0 ;
+    PyObject *result ;
+    
+    if(!PyArg_ParseTuple(args,"O:SHPObject_extents",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_SHPObject,1)) == -1) return NULL;
+    result = (PyObject *)SHPObject_extents(arg0);
+    {
+        resultobj = result;
+    }
+    return resultobj;
+}
+
+
+static PyObject *_wrap_SHPObject_vertices(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    SHPObject *arg0 ;
+    PyObject * argo0 =0 ;
+    PyObject *result ;
+    
+    if(!PyArg_ParseTuple(args,"O:SHPObject_vertices",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_SHPObject,1)) == -1) return NULL;
+    result = (PyObject *)SHPObject_vertices(arg0);
+    {
+        resultobj = result;
+    }
+    return resultobj;
+}
+
+
+ShapeFile * new_ShapeFile(char *file,char *mode) {
+    {
+        ShapeFile * self = malloc(sizeof(ShapeFile));
+        if (self)
+        self->handle = SHPOpen(file, mode);
+        return self;
+    }
+}
+
+
+static PyObject *_wrap_new_ShapeFile(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    char *arg0 ;
+    char *arg1 = "rb" ;
+    ShapeFile *result ;
+    
+    if(!PyArg_ParseTuple(args,"s|s:new_ShapeFile",&arg0,&arg1)) return NULL;
+    {
+        result = (ShapeFile *)new_ShapeFile(arg0,arg1);
+        ;
+        if (!result)
+        {
+            SWIG_exception(SWIG_MemoryError, "no memory");
+        }
+        else if (!result->handle)
+        {
+            SWIG_exception(SWIG_IOError, "new_ShapeFile failed");
+        }
+    }resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_ShapeFile);
+    return resultobj;
+}
+
+
+void  delete_ShapeFile(ShapeFile *self) {
+    {
+        if (self->handle)
+        SHPClose(self->handle);
+        free(self);
+    }
+}
+
+
+static PyObject *_wrap_delete_ShapeFile(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    ShapeFile *arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:delete_ShapeFile",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_ShapeFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_delete_ShapeFile
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "shapefile already closed");
+        #endif
+    }
+    delete_ShapeFile(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+void  ShapeFile_close(ShapeFile *self) {
+    {
+        if (self->handle)
+        {
+            SHPClose(self->handle);
+            self->handle = NULL;
+        }
+    }
+}
+
+
+static PyObject *_wrap_ShapeFile_close(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    ShapeFile *arg0 ;
+    PyObject * argo0 =0 ;
+    
+    if(!PyArg_ParseTuple(args,"O:ShapeFile_close",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_ShapeFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_ShapeFile_close
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "shapefile already closed");
+        #endif
+    }
+    ShapeFile_close(arg0);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    return resultobj;
+}
+
+
+void  ShapeFile_info(ShapeFile *self,int *output_entities,int *output_type,double *output_min_bounds,double *output_max_bounds) {
+    {
+        SHPGetInfo(self->handle, output_entities, output_type,
+        output_min_bounds, output_max_bounds);
+    }
+}
+
+
+static PyObject *_wrap_ShapeFile_info(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    ShapeFile *arg0 ;
+    int *arg1 ;
+    int *arg2 ;
+    double *arg3 ;
+    double *arg4 ;
+    int temp ;
+    int temp0 ;
+    double temp1[4] ;
+    double temp2[4] ;
+    PyObject * argo0 =0 ;
+    
+    {
+        arg1 = &temp;
+    }
+    {
+        arg2 = &temp0;
+    }
+    {
+        arg3 = temp1;
+    }
+    {
+        arg4 = temp2;
+    }
+    if(!PyArg_ParseTuple(args,"O:ShapeFile_info",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_ShapeFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_ShapeFile_info
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "shapefile already closed");
+        #endif
+    }
+    ShapeFile_info(arg0,arg1,arg2,arg3,arg4);
+    Py_INCREF(Py_None);
+    resultobj = Py_None;
+    {
+        PyObject *o;
+        o = PyInt_FromLong((long) (*arg1));
+        resultobj = t_output_helper(resultobj, o);
+    }
+    {
+        PyObject *o;
+        o = PyInt_FromLong((long) (*arg2));
+        resultobj = t_output_helper(resultobj, o);
+    }
+    {
+        PyObject * list = Py_BuildValue("[dddd]",
+        arg3[0], arg3[1],
+        arg3[2], arg3[3]);
+        resultobj = t_output_helper(resultobj,list);
+    }
+    {
+        PyObject * list = Py_BuildValue("[dddd]",
+        arg4[0], arg4[1],
+        arg4[2], arg4[3]);
+        resultobj = t_output_helper(resultobj,list);
+    }
+    return resultobj;
+}
+
+
+SHPObject * ShapeFile_read_object(ShapeFile *self,int i) {
+    {
+        return SHPReadObject(self->handle, i);
+    }
+}
+
+
+static PyObject *_wrap_ShapeFile_read_object(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    ShapeFile *arg0 ;
+    int arg1 ;
+    PyObject * argo0 =0 ;
+    SHPObject *result ;
+    
+    if(!PyArg_ParseTuple(args,"Oi:ShapeFile_read_object",&argo0,&arg1)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_ShapeFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_ShapeFile_read_object
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "shapefile already closed");
+        #endif
+    }
+    result = (SHPObject *)ShapeFile_read_object(arg0,arg1);
+    resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_SHPObject);
+    return resultobj;
+}
+
+
+int  ShapeFile_write_object(ShapeFile *self,int iShape,SHPObject *psObject) {
+    {
+        return SHPWriteObject(self->handle, iShape, psObject);
+    }
+}
+
+
+static PyObject *_wrap_ShapeFile_write_object(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    ShapeFile *arg0 ;
+    int arg1 ;
+    SHPObject *arg2 ;
+    PyObject * argo0 =0 ;
+    PyObject * argo2 =0 ;
+    int result ;
+    
+    if(!PyArg_ParseTuple(args,"OiO:ShapeFile_write_object",&argo0,&arg1,&argo2)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_ShapeFile,1)) == -1) return NULL;
+    if ((SWIG_ConvertPtr(argo2,(void **) &arg2,SWIGTYPE_p_SHPObject,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_ShapeFile_write_object
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "shapefile already closed");
+        #endif
+    }
+    result = (int )ShapeFile_write_object(arg0,arg1,arg2);
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+}
+
+
+PyObject * ShapeFile_cobject(ShapeFile *self) {
+    {
+        return PyCObject_FromVoidPtr(self->handle, NULL);
+    }
+}
+
+
+static PyObject *_wrap_ShapeFile_cobject(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    ShapeFile *arg0 ;
+    PyObject * argo0 =0 ;
+    PyObject *result ;
+    
+    if(!PyArg_ParseTuple(args,"O:ShapeFile_cobject",&argo0)) return NULL;
+    if ((SWIG_ConvertPtr(argo0,(void **) &arg0,SWIGTYPE_p_ShapeFile,1)) == -1) return NULL;
+    {
+        #ifndef NOCHECK_ShapeFile_cobject
+        if (!arg0 || !arg0->handle)
+        SWIG_exception(SWIG_TypeError, "shapefile already closed");
+        #endif
+    }
+    result = (PyObject *)ShapeFile_cobject(arg0);
+    {
+        resultobj = result;
+    }
+    return resultobj;
+}
+
+
+static PyMethodDef shapelibcMethods[] = {
+	 { "open", _wrap_open, METH_VARARGS },
+	 { "create", _wrap_create, METH_VARARGS },
+	 { "c_api", _wrap_c_api, METH_VARARGS },
+	 { "type_name", _wrap_type_name, METH_VARARGS },
+	 { "part_type_name", _wrap_part_type_name, METH_VARARGS },
+	 { "SHPObject_type_get", _wrap_SHPObject_type_get, METH_VARARGS },
+	 { "SHPObject_id_get", _wrap_SHPObject_id_get, METH_VARARGS },
+	 { "new_SHPObject", _wrap_new_SHPObject, METH_VARARGS },
+	 { "delete_SHPObject", _wrap_delete_SHPObject, METH_VARARGS },
+	 { "SHPObject_extents", _wrap_SHPObject_extents, METH_VARARGS },
+	 { "SHPObject_vertices", _wrap_SHPObject_vertices, METH_VARARGS },
+	 { "new_ShapeFile", _wrap_new_ShapeFile, METH_VARARGS },
+	 { "delete_ShapeFile", _wrap_delete_ShapeFile, METH_VARARGS },
+	 { "ShapeFile_close", _wrap_ShapeFile_close, METH_VARARGS },
+	 { "ShapeFile_info", _wrap_ShapeFile_info, METH_VARARGS },
+	 { "ShapeFile_read_object", _wrap_ShapeFile_read_object, METH_VARARGS },
+	 { "ShapeFile_write_object", _wrap_ShapeFile_write_object, METH_VARARGS },
+	 { "ShapeFile_cobject", _wrap_ShapeFile_cobject, METH_VARARGS },
+	 { NULL, NULL }
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
+
+static swig_type_info _swigt__p_ShapeFile[] = {{"_p_ShapeFile", 0, "ShapeFile *"},{"_p_ShapeFile"},{0}};
+static swig_type_info _swigt__p_SHPObject[] = {{"_p_SHPObject", 0, "SHPObject *"},{"_p_SHPObject"},{0}};
+
+static swig_type_info *swig_types_initial[] = {
+_swigt__p_ShapeFile, 
+_swigt__p_SHPObject, 
+0
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
+
+static swig_const_info swig_const_table[] = {
+    { SWIG_PY_INT,     "SHPT_NULL", (long) 0, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_POINT", (long) 1, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_ARC", (long) 3, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_POLYGON", (long) 5, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_MULTIPOINT", (long) 8, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_POINTZ", (long) 11, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_ARCZ", (long) 13, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_POLYGONZ", (long) 15, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_MULTIPOINTZ", (long) 18, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_POINTM", (long) 21, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_ARCM", (long) 23, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_POLYGONM", (long) 25, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_MULTIPOINTM", (long) 28, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPT_MULTIPATCH", (long) 31, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPP_TRISTRIP", (long) 0, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPP_TRIFAN", (long) 1, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPP_OUTERRING", (long) 2, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPP_INNERRING", (long) 3, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPP_FIRSTRING", (long) 4, 0, 0, 0},
+    { SWIG_PY_INT,     "SHPP_RING", (long) 5, 0, 0, 0},
+{0}};
+
+static PyObject *SWIG_globals;
+#ifdef __cplusplus
+extern "C" 
+#endif
+SWIGEXPORT(void) initshapelibc(void) {
+    PyObject *m, *d;
+    int i;
+    SWIG_globals = SWIG_newvarlink();
+    m = Py_InitModule("shapelibc", shapelibcMethods);
+    d = PyModule_GetDict(m);
+    for (i = 0; swig_types_initial[i]; i++) {
+        swig_types[i] = SWIG_TypeRegister(swig_types_initial[i]);
+    }
+    SWIG_InstallConstants(d,swig_const_table);
+}
+

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/shptreemodule.c
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/shptreemodule.c	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/shptreemodule.c	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,176 @@
+/* Copyright (c) 2001, 2002 by Intevation GmbH
+ * Authors:
+ * Bernhard Herzog <bh at intevation.de>
+ *
+ * This program is free software under the GPL (>=v2)
+ * Read the file COPYING coming with Thuban for details.
+ */
+
+/* Python wrapper for the shapelib SHPTree */
+
+#include <Python.h>
+#include <shapefil.h>
+
+#include "pyshapelib_api.h"
+
+PyShapeLibAPI * api;
+
+typedef struct {
+    PyObject_HEAD
+    SHPTree * tree; 
+} SHPTreeObject;
+
+extern PyTypeObject SHPTreeType;
+
+#define SHPTree_Check(v)		((v)->ob_type == &SHPTreeType)
+
+/* Create a new python wrapper object from a SHPTree pointer */
+static PyObject *
+SHPTreeObject_FromSHPTree(SHPTree* tree)
+{
+    SHPTreeObject * self = PyObject_NEW(SHPTreeObject, &SHPTreeType);
+    if (!self)
+	return NULL;
+
+    self->tree = tree;
+
+    return (PyObject *)self;
+}
+
+/* Deallocate the SHPTree wrapper. */
+static void
+shptree_dealloc(SHPTreeObject * self)
+{
+    api->SHPDestroyTree(self->tree);
+    PyMem_DEL(self);
+}
+
+/* Return the repr of the wrapper */
+static PyObject *
+shptree_repr(SHPTreeObject * self)
+{
+    char buf[1000];
+    sprintf(buf, "<SHPTree at %xul>", (unsigned long)self);
+    return PyString_FromString(buf);
+}
+
+static PyObject *
+shptree_find_shapes(SHPTreeObject * self, PyObject * args)
+{
+    double min[4] = {0, 0, 0, 0};
+    double max[4] = {0, 0, 0, 0};
+    int count, idx;
+    int * ids;
+    PyObject * list = NULL, *temp = NULL;
+
+    if (!PyArg_ParseTuple(args, "(dd)(dd)", min + 0, min + 1,
+			  max + 0, max + 1))
+	return NULL;
+
+    ids = api->SHPTreeFindLikelyShapes(self->tree, min, max, &count);
+
+    list = PyList_New(count);
+    if (!list)
+	goto fail;
+
+    /* Turn the returned array of indices into a python list of ints. */
+    for (idx = 0; idx < count; idx++)
+    {
+	temp = PyInt_FromLong(ids[idx]);
+	if (!temp)
+	    goto fail;
+
+	if (PyList_SetItem(list, idx, temp) == -1)
+	{
+	    /* temp's refcount has already be decreased. Set temp to
+	     * NULL so that the fail code doesn't do it again
+	     */
+	    temp = NULL;
+	    goto fail;
+	}
+    }
+
+    free(ids);
+    return list;
+    
+ fail:
+    free(ids);
+    Py_XDECREF(list);
+    Py_XDECREF(temp);
+    return NULL;
+}
+
+
+static struct PyMethodDef shptree_methods[] = {
+    {"find_shapes",	(PyCFunction)shptree_find_shapes,	METH_VARARGS},
+    {NULL,	NULL}
+};
+
+static PyObject *
+shptree_getattr(PyObject * self, char * name)
+{
+    return Py_FindMethod(shptree_methods, self, name);
+}
+
+
+PyTypeObject SHPTreeType = {
+	PyObject_HEAD_INIT(NULL)
+	0,
+	"SHPTree",
+	sizeof(SHPTreeObject),
+	0,
+	(destructor)shptree_dealloc,	/*tp_dealloc*/
+	(printfunc)NULL,		/*tp_print*/
+	shptree_getattr,		/*tp_getattr*/
+	0,				/*tp_setattr*/
+	0,				/*tp_compare*/
+	(reprfunc)shptree_repr,		/*tp_repr*/
+	0,				/*tp_as_number*/
+	0,				/*tp_as_sequence*/
+	0,				/*tp_as_mapping*/
+	0,				/*tp_hash*/
+        0,				/*tp_call*/
+        0,				/*tp_str*/
+	0,				/*tp_getattro*/
+	0,				/*tp_setattro*/
+	0,				/*tp_as_buffer*/
+};
+
+
+
+static PyObject *
+shptree_from_shapefile(PyObject * self, PyObject * args)
+{
+    SHPTree * tree;
+    SHPHandle handle;
+    PyObject * cobject;
+    int dimension, max_depth;
+
+    if (!PyArg_ParseTuple(args, "O!ii", &PyCObject_Type, &cobject,
+			  &dimension, &max_depth))
+	return NULL;
+
+    handle = PyCObject_AsVoidPtr(cobject);
+
+    tree = api->SHPCreateTree(handle, dimension, max_depth, NULL, NULL);
+
+    /* apparently SHPCreateTree doesn't do any error checking, so we
+     * have to assume that tree is valid at this point. */
+    return SHPTreeObject_FromSHPTree(tree);
+}
+
+
+static PyMethodDef module_functions[] = {
+    {"SHPTree",		shptree_from_shapefile,		METH_VARARGS},
+    { NULL, NULL }
+};
+
+
+void
+initshptree()
+{
+    SHPTreeType.ob_type = &PyType_Type;
+
+    Py_InitModule("shptree", module_functions);
+    PYSHAPELIB_IMPORT_API(api);
+}

Added: packages/thuban/branches/upstream/current/libraries/pyshapelib/testdbf.py
===================================================================
--- packages/thuban/branches/upstream/current/libraries/pyshapelib/testdbf.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/pyshapelib/testdbf.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,28 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the LGPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Test cases for the dbflib python bindings"""
+
+__version__ = "$Revision: 1762 $"
+# $Source$
+# $Id: testdbf.py 1762 2003-09-29 10:52:38Z bh $
+
+import unittest
+import dbflib
+
+class TestDBF(unittest.TestCase):
+
+    def test_add_field(self):
+        """Test whethe add_field reports exceptions"""
+        dbf = dbflib.create("test.dbf")
+        # For strings the precision parameter must be 0
+        self.assertRaises(RuntimeError,
+                          dbf.add_field, "str", dbflib.FTString, 10, 5)
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/libraries/shapelib/dbfopen.c
===================================================================
--- packages/thuban/branches/upstream/current/libraries/shapelib/dbfopen.c	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/shapelib/dbfopen.c	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1594 @@
+/******************************************************************************
+ * $Id: dbfopen.c 2703 2006-09-24 18:51:39Z bernhard $
+ *
+ * Project:  Shapelib
+ * Purpose:  Implementation of .dbf access API documented in dbf_api.html.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log$
+ * Revision 1.3  2004/05/17 15:47:57  bh
+ * Update to newest shapelib and get rid of Thuban specific extensions,
+ * i.e. use the new DBFUpdateHeader instead of our DBFCommit kludge
+ *
+ * * libraries/shapelib/shpopen.c: Update to version from current
+ * shapelib CVS.
+ *
+ * * libraries/shapelib/shapefil.h: Update to version from current
+ * shapelib CVS.
+ *
+ * * libraries/shapelib/dbfopen.c: Update to version from current
+ * shapelib CVS.
+ * (DBFCommit): Effectively removed since shapelib itself has
+ * DBFUpdateHeader now which is better for what DBFCommit wanted to
+ * achieve.
+ * We're now using an unmodified version of dbfopen.
+ *
+ * * libraries/pyshapelib/dbflib_wrap.c, libraries/pyshapelib/dbflib.py:
+ * Update from dbflib.i
+ *
+ * * libraries/pyshapelib/dbflib.i (DBFInfo_commit): New. Implementation of
+ * the commit method.  This new indirection is necessary because we use the
+ * DBFUpdateHeader function now which is not available in shapelib <=
+ * 1.2.10
+ * (DBFFile::commit): Use DBFInfo_commit as implementation
+ * (pragma __class__): New. Kludge to remove the commit method when
+ * the DBFUpdateHeader function isn't available
+ * (_have_commit): New. Helper for the pragma kludge.
+ *
+ * * libraries/pyshapelib/setup.py (dbf_macros): New. Return the
+ * preprocessor macros needed to compile the dbflib wrapper.  Determine
+ * whether DBFUpdateHeader is available and define the right value of
+ * HAVE_UPDATE_HEADER
+ * (extensions): Use dbf_macros for the dbflibc extension
+ *
+ * * setup.py (extensions): Add the HAVE_UPDATE_HEADER macro with
+ * value '1' to the Lib.dbflibc extension.  This simply reflects the
+ * shapelib and pyshapelib updates
+ *
+ * Revision 1.53  2003/12/29 00:00:30  fwarmerdam
+ * mark DBFWriteAttributeDirectly as SHPAPI_CALL
+ *
+ * Revision 1.52  2003/07/08 15:20:03  warmerda
+ * avoid warnings about downcasting to unsigned char
+ *
+ * Revision 1.51  2003/07/08 13:50:15  warmerda
+ * DBFIsAttributeNULL check for pszValue==NULL - bug 360
+ *
+ * Revision 1.50  2003/04/21 18:58:25  warmerda
+ * ensure current record is flushed at same time as header is updated
+ *
+ * Revision 1.49  2003/04/21 18:30:37  warmerda
+ * added header write/update public methods
+ *
+ * Revision 1.48  2003/03/10 14:51:27  warmerda
+ * DBFWrite* calls now return FALSE if they have to truncate
+ *
+ * Revision 1.47  2002/11/20 03:32:22  warmerda
+ * Ensure field name in DBFGetFieldIndex() is properly terminated.
+ *
+ * Revision 1.46  2002/10/09 13:10:21  warmerda
+ * Added check that width is positive.
+ *
+ * Revision 1.45  2002/09/29 00:00:08  warmerda
+ * added FTLogical and logical attribute read/write calls
+ *
+ * Revision 1.44  2002/05/07 13:46:11  warmerda
+ * Added DBFWriteAttributeDirectly().
+ *
+ * Revision 1.43  2002/02/13 19:39:21  warmerda
+ * Fix casting issues in DBFCloneEmpty().
+ *
+ * Revision 1.42  2002/01/15 14:36:07  warmerda
+ * updated email address
+ *
+ * Revision 1.41  2002/01/15 14:31:49  warmerda
+ * compute rather than copying nHeaderLength in DBFCloneEmpty()
+ *
+ * Revision 1.40  2002/01/09 04:32:35  warmerda
+ * fixed to read correct amount of header
+ *
+ * Revision 1.39  2001/12/11 22:41:03  warmerda
+ * improve io related error checking when reading header
+ *
+ * Revision 1.38  2001/11/28 16:07:31  warmerda
+ * Cleanup to avoid compiler warnings as suggested by Richard Hash.
+ *
+ * Revision 1.37  2001/07/04 05:18:09  warmerda
+ * do last fix properly
+ *
+ * Revision 1.36  2001/07/04 05:16:09  warmerda
+ * fixed fieldname comparison in DBFGetFieldIndex
+ *
+ * Revision 1.35  2001/06/22 02:10:06  warmerda
+ * fixed NULL shape support with help from Jim Matthews
+ *
+ * Revision 1.33  2001/05/31 19:20:13  warmerda
+ * added DBFGetFieldIndex()
+ *
+ * Revision 1.32  2001/05/31 18:15:40  warmerda
+ * Added support for NULL fields in DBF files
+ *
+ * Revision 1.31  2001/05/23 13:36:52  warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.30  2000/12/05 14:43:38  warmerda
+ * DBReadAttribute() white space trimming bug fix
+ *
+ * Revision 1.29  2000/10/05 14:36:44  warmerda
+ * fix bug with writing very wide numeric fields
+ *
+ * Revision 1.28  2000/09/25 14:18:07  warmerda
+ * Added some casts of strlen() return result to fix warnings on some
+ * systems, as submitted by Daniel.
+ *
+ * Revision 1.27  2000/09/25 14:15:51  warmerda
+ * added DBFGetNativeFieldType()
+ *
+ * Revision 1.26  2000/07/07 13:39:45  warmerda
+ * removed unused variables, and added system include files
+ *
+ * Revision 1.25  2000/05/29 18:19:13  warmerda
+ * avoid use of uchar, and adding casting fix
+ *
+ * Revision 1.24  2000/05/23 13:38:27  warmerda
+ * Added error checks on return results of fread() and fseek().
+ *
+ * Revision 1.23  2000/05/23 13:25:49  warmerda
+ * Avoid crashing if field or record are out of range in dbfread*attribute().
+ *
+ * Revision 1.22  1999/12/15 13:47:24  warmerda
+ * Added stdlib.h to ensure that atof() is prototyped.
+ *
+ * Revision 1.21  1999/12/13 17:25:46  warmerda
+ * Added support for upper case .DBF extention.
+ *
+ * Revision 1.20  1999/11/30 16:32:11  warmerda
+ * Use atof() instead of sscanf().
+ *
+ * Revision 1.19  1999/11/05 14:12:04  warmerda
+ * updated license terms
+ *
+ * Revision 1.18  1999/07/27 00:53:28  warmerda
+ * ensure that whole old field value clear on write of string
+ *
+ * Revision 1.1  1999/07/05 18:58:07  warmerda
+ * New
+ *
+ * Revision 1.17  1999/06/11 19:14:12  warmerda
+ * Fixed some memory leaks.
+ *
+ * Revision 1.16  1999/06/11 19:04:11  warmerda
+ * Remoted some unused variables.
+ *
+ * Revision 1.15  1999/05/11 03:19:28  warmerda
+ * added new Tuple api, and improved extension handling - add from candrsn
+ *
+ * Revision 1.14  1999/05/04 15:01:48  warmerda
+ * Added 'F' support.
+ *
+ * Revision 1.13  1999/03/23 17:38:59  warmerda
+ * DBFAddField() now actually does return the new field number, or -1 if
+ * it fails.
+ *
+ * Revision 1.12  1999/03/06 02:54:46  warmerda
+ * Added logic to convert shapefile name to dbf filename in DBFOpen()
+ * for convenience.
+ *
+ * Revision 1.11  1998/12/31 15:30:34  warmerda
+ * Improved the interchangability of numeric and string attributes.  Add
+ * white space trimming option for attributes.
+ *
+ * Revision 1.10  1998/12/03 16:36:44  warmerda
+ * Use r+b instead of rb+ for binary access.
+ *
+ * Revision 1.9  1998/12/03 15:34:23  warmerda
+ * Updated copyright message.
+ *
+ * Revision 1.8  1997/12/04 15:40:15  warmerda
+ * Added newline character after field definitions.
+ *
+ * Revision 1.7  1997/03/06 14:02:10  warmerda
+ * Ensure bUpdated is initialized.
+ *
+ * Revision 1.6  1996/02/12 04:54:41  warmerda
+ * Ensure that DBFWriteAttribute() returns TRUE if it succeeds.
+ *
+ * Revision 1.5  1995/10/21  03:15:12  warmerda
+ * Changed to use binary file access, and ensure that the
+ * field name field is zero filled, and limited to 10 chars.
+ *
+ * Revision 1.4  1995/08/24  18:10:42  warmerda
+ * Added use of SfRealloc() to avoid pre-ANSI realloc() functions such
+ * as on the Sun.
+ *
+ * Revision 1.3  1995/08/04  03:15:16  warmerda
+ * Fixed up header.
+ *
+ * Revision 1.2  1995/08/04  03:14:43  warmerda
+ * Added header.
+ */
+
+static char rcsid[] = 
+  "$Id: dbfopen.c 2703 2006-09-24 18:51:39Z bernhard $";
+
+#include "shapefil.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#ifndef FALSE
+#  define FALSE		0
+#  define TRUE		1
+#endif
+
+static int	nStringFieldLen = 0;
+static char * pszStringField = NULL;
+
+/************************************************************************/
+/*                             DBFSet_atof_function()                   */
+/*                                                                      */
+/* This makes it possible to initialise a different atof() function	*/
+/* which might be necessary because the standard atof() might be        */
+/* sensitive to locale settings.                                        */
+/*                                                                      */
+/* If the calling application uses a locale with different decimal_point*/
+/* it should better also give us a locale agnostic atof() function.     */
+/*                                                                      */
+/* As far as I can see from Python PEP331 and GNU libc documentation    */
+/* there is no standard for such a function yet.                        */
+/*                                                                      */
+/* bernhard.reiter at intevation.de 20060924                               */
+/************************************************************************/
+
+static double (* atof_function)(const char *nptr)  = &atof;
+
+void SHPAPI_CALL
+	DBFSetatof_function(  double (* new_atof_function)(const char *nptr)) 
+{
+	atof_function = new_atof_function;
+}
+
+/************************************************************************/
+/*                             SfRealloc()                              */
+/*                                                                      */
+/*      A realloc cover function that will access a NULL pointer as     */
+/*      a valid input.                                                  */
+/************************************************************************/
+
+static void * SfRealloc( void * pMem, int nNewSize )
+
+{
+    if( pMem == NULL )
+        return( (void *) malloc(nNewSize) );
+    else
+        return( (void *) realloc(pMem,nNewSize) );
+}
+
+/************************************************************************/
+/*                           DBFWriteHeader()                           */
+/*                                                                      */
+/*      This is called to write out the file header, and field          */
+/*      descriptions before writing any actual data records.  This      */
+/*      also computes all the DBFDataSet field offset/size/decimals     */
+/*      and so forth values.                                            */
+/************************************************************************/
+
+static void DBFWriteHeader(DBFHandle psDBF)
+
+{
+    unsigned char	abyHeader[XBASE_FLDHDR_SZ];
+    int		i;
+
+    if( !psDBF->bNoHeader )
+        return;
+
+    psDBF->bNoHeader = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*	Initialize the file header information.				*/
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
+        abyHeader[i] = 0;
+
+    abyHeader[0] = 0x03;		/* memo field? - just copying 	*/
+
+    /* write out a dummy date */
+    abyHeader[1] = 95;			/* YY */
+    abyHeader[2] = 7;			/* MM */
+    abyHeader[3] = 26;			/* DD */
+
+    /* record count preset at zero */
+
+    abyHeader[8] = (unsigned char) (psDBF->nHeaderLength % 256);
+    abyHeader[9] = (unsigned char) (psDBF->nHeaderLength / 256);
+    
+    abyHeader[10] = (unsigned char) (psDBF->nRecordLength % 256);
+    abyHeader[11] = (unsigned char) (psDBF->nRecordLength / 256);
+
+/* -------------------------------------------------------------------- */
+/*      Write the initial 32 byte file header, and all the field        */
+/*      descriptions.                                     		*/
+/* -------------------------------------------------------------------- */
+    fseek( psDBF->fp, 0, 0 );
+    fwrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
+    fwrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields, psDBF->fp );
+
+/* -------------------------------------------------------------------- */
+/*      Write out the newline character if there is room for it.        */
+/* -------------------------------------------------------------------- */
+    if( psDBF->nHeaderLength > 32*psDBF->nFields + 32 )
+    {
+        char	cNewline;
+
+        cNewline = 0x0d;
+        fwrite( &cNewline, 1, 1, psDBF->fp );
+    }
+}
+
+/************************************************************************/
+/*                           DBFFlushRecord()                           */
+/*                                                                      */
+/*      Write out the current record if there is one.                   */
+/************************************************************************/
+
+static void DBFFlushRecord( DBFHandle psDBF )
+
+{
+    int		nRecordOffset;
+
+    if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
+    {
+	psDBF->bCurrentRecordModified = FALSE;
+
+	nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord 
+	                                             + psDBF->nHeaderLength;
+
+	fseek( psDBF->fp, nRecordOffset, 0 );
+	fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+    }
+}
+
+/************************************************************************/
+/*                          DBFUpdateHeader()                           */
+/************************************************************************/
+
+void SHPAPI_CALL
+DBFUpdateHeader( DBFHandle psDBF )
+
+{
+    unsigned char		abyFileHeader[32];
+
+    if( psDBF->bNoHeader )
+        DBFWriteHeader( psDBF );
+
+    DBFFlushRecord( psDBF );
+
+    fseek( psDBF->fp, 0, 0 );
+    fread( abyFileHeader, 32, 1, psDBF->fp );
+    
+    abyFileHeader[4] = (unsigned char) (psDBF->nRecords % 256);
+    abyFileHeader[5] = (unsigned char) ((psDBF->nRecords/256) % 256);
+    abyFileHeader[6] = (unsigned char) ((psDBF->nRecords/(256*256)) % 256);
+    abyFileHeader[7] = (unsigned char) ((psDBF->nRecords/(256*256*256)) % 256);
+    
+    fseek( psDBF->fp, 0, 0 );
+    fwrite( abyFileHeader, 32, 1, psDBF->fp );
+
+    fflush( psDBF->fp );
+}
+
+/************************************************************************/
+/*                              DBFOpen()                               */
+/*                                                                      */
+/*      Open a .dbf file.                                               */
+/************************************************************************/
+   
+DBFHandle SHPAPI_CALL
+DBFOpen( const char * pszFilename, const char * pszAccess )
+
+{
+    DBFHandle		psDBF;
+    unsigned char		*pabyBuf;
+    int			nFields, nHeadLen, nRecLen, iField, i;
+    char		*pszBasename, *pszFullname;
+
+/* -------------------------------------------------------------------- */
+/*      We only allow the access strings "rb" and "r+".                  */
+/* -------------------------------------------------------------------- */
+    if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0 
+        && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
+        && strcmp(pszAccess,"r+b") != 0 )
+        return( NULL );
+
+    if( strcmp(pszAccess,"r") == 0 )
+        pszAccess = "rb";
+ 
+    if( strcmp(pszAccess,"r+") == 0 )
+        pszAccess = "rb+";
+
+/* -------------------------------------------------------------------- */
+/*	Compute the base (layer) name.  If there is any extension	*/
+/*	on the passed in filename we will strip it off.			*/
+/* -------------------------------------------------------------------- */
+    pszBasename = (char *) malloc(strlen(pszFilename)+5);
+    strcpy( pszBasename, pszFilename );
+    for( i = strlen(pszBasename)-1; 
+	 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+	       && pszBasename[i] != '\\';
+	 i-- ) {}
+
+    if( pszBasename[i] == '.' )
+        pszBasename[i] = '\0';
+
+    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+    sprintf( pszFullname, "%s.dbf", pszBasename );
+        
+    psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
+    psDBF->fp = fopen( pszFullname, pszAccess );
+
+    if( psDBF->fp == NULL )
+    {
+        sprintf( pszFullname, "%s.DBF", pszBasename );
+        psDBF->fp = fopen(pszFullname, pszAccess );
+    }
+    
+    free( pszBasename );
+    free( pszFullname );
+    
+    if( psDBF->fp == NULL )
+    {
+        free( psDBF );
+        return( NULL );
+    }
+
+    psDBF->bNoHeader = FALSE;
+    psDBF->nCurrentRecord = -1;
+    psDBF->bCurrentRecordModified = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*  Read Table Header info                                              */
+/* -------------------------------------------------------------------- */
+    pabyBuf = (unsigned char *) malloc(500);
+    if( fread( pabyBuf, 32, 1, psDBF->fp ) != 1 )
+    {
+        fclose( psDBF->fp );
+        free( pabyBuf );
+        free( psDBF );
+        return NULL;
+    }
+
+    psDBF->nRecords = 
+     pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + pabyBuf[7]*256*256*256;
+
+    psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
+    psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;
+    
+    psDBF->nFields = nFields = (nHeadLen - 32) / 32;
+
+    psDBF->pszCurrentRecord = (char *) malloc(nRecLen);
+
+/* -------------------------------------------------------------------- */
+/*  Read in Field Definitions                                           */
+/* -------------------------------------------------------------------- */
+    
+    pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
+    psDBF->pszHeader = (char *) pabyBuf;
+
+    fseek( psDBF->fp, 32, 0 );
+    if( fread( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
+    {
+        fclose( psDBF->fp );
+        free( pabyBuf );
+        free( psDBF );
+        return NULL;
+    }
+
+    psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
+    psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
+    psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
+    psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);
+
+    for( iField = 0; iField < nFields; iField++ )
+    {
+	unsigned char		*pabyFInfo;
+
+	pabyFInfo = pabyBuf+iField*32;
+
+	if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
+	{
+	    psDBF->panFieldSize[iField] = pabyFInfo[16];
+	    psDBF->panFieldDecimals[iField] = pabyFInfo[17];
+	}
+	else
+	{
+	    psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
+	    psDBF->panFieldDecimals[iField] = 0;
+	}
+
+	psDBF->pachFieldType[iField] = (char) pabyFInfo[11];
+	if( iField == 0 )
+	    psDBF->panFieldOffset[iField] = 1;
+	else
+	    psDBF->panFieldOffset[iField] = 
+	      psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
+    }
+
+    return( psDBF );
+}
+
+/************************************************************************/
+/*                              DBFClose()                              */
+/************************************************************************/
+
+void SHPAPI_CALL
+DBFClose(DBFHandle psDBF)
+{
+/* -------------------------------------------------------------------- */
+/*      Write out header if not already written.                        */
+/* -------------------------------------------------------------------- */
+    if( psDBF->bNoHeader )
+        DBFWriteHeader( psDBF );
+
+    DBFFlushRecord( psDBF );
+
+/* -------------------------------------------------------------------- */
+/*      Update last access date, and number of records if we have	*/
+/*	write access.                					*/
+/* -------------------------------------------------------------------- */
+    if( psDBF->bUpdated )
+        DBFUpdateHeader( psDBF );
+
+/* -------------------------------------------------------------------- */
+/*      Close, and free resources.                                      */
+/* -------------------------------------------------------------------- */
+    fclose( psDBF->fp );
+
+    if( psDBF->panFieldOffset != NULL )
+    {
+        free( psDBF->panFieldOffset );
+        free( psDBF->panFieldSize );
+        free( psDBF->panFieldDecimals );
+        free( psDBF->pachFieldType );
+    }
+
+    free( psDBF->pszHeader );
+    free( psDBF->pszCurrentRecord );
+
+    free( psDBF );
+
+    if( pszStringField != NULL )
+    {
+        free( pszStringField );
+        pszStringField = NULL;
+        nStringFieldLen = 0;
+    }
+}
+
+/************************************************************************/
+/*                             DBFCreate()                              */
+/*                                                                      */
+/*      Create a new .dbf file.                                         */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFCreate( const char * pszFilename )
+
+{
+    DBFHandle	psDBF;
+    FILE	*fp;
+    char	*pszFullname, *pszBasename;
+    int		i;
+
+/* -------------------------------------------------------------------- */
+/*	Compute the base (layer) name.  If there is any extension	*/
+/*	on the passed in filename we will strip it off.			*/
+/* -------------------------------------------------------------------- */
+    pszBasename = (char *) malloc(strlen(pszFilename)+5);
+    strcpy( pszBasename, pszFilename );
+    for( i = strlen(pszBasename)-1; 
+	 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+	       && pszBasename[i] != '\\';
+	 i-- ) {}
+
+    if( pszBasename[i] == '.' )
+        pszBasename[i] = '\0';
+
+    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+    sprintf( pszFullname, "%s.dbf", pszBasename );
+    free( pszBasename );
+
+/* -------------------------------------------------------------------- */
+/*      Create the file.                                                */
+/* -------------------------------------------------------------------- */
+    fp = fopen( pszFullname, "wb" );
+    if( fp == NULL )
+        return( NULL );
+
+    fputc( 0, fp );
+    fclose( fp );
+
+    fp = fopen( pszFullname, "rb+" );
+    if( fp == NULL )
+        return( NULL );
+
+    free( pszFullname );
+
+/* -------------------------------------------------------------------- */
+/*	Create the info structure.					*/
+/* -------------------------------------------------------------------- */
+    psDBF = (DBFHandle) malloc(sizeof(DBFInfo));
+
+    psDBF->fp = fp;
+    psDBF->nRecords = 0;
+    psDBF->nFields = 0;
+    psDBF->nRecordLength = 1;
+    psDBF->nHeaderLength = 33;
+    
+    psDBF->panFieldOffset = NULL;
+    psDBF->panFieldSize = NULL;
+    psDBF->panFieldDecimals = NULL;
+    psDBF->pachFieldType = NULL;
+    psDBF->pszHeader = NULL;
+
+    psDBF->nCurrentRecord = -1;
+    psDBF->bCurrentRecordModified = FALSE;
+    psDBF->pszCurrentRecord = NULL;
+
+    psDBF->bNoHeader = TRUE;
+
+    return( psDBF );
+}
+
+/************************************************************************/
+/*                            DBFAddField()                             */
+/*                                                                      */
+/*      Add a field to a newly created .dbf file before any records     */
+/*      are written.                                                    */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFAddField(DBFHandle psDBF, const char * pszFieldName, 
+            DBFFieldType eType, int nWidth, int nDecimals )
+
+{
+    char	*pszFInfo;
+    int		i;
+
+/* -------------------------------------------------------------------- */
+/*      Do some checking to ensure we can add records to this file.     */
+/* -------------------------------------------------------------------- */
+    if( psDBF->nRecords > 0 )
+        return( -1 );
+
+    if( !psDBF->bNoHeader )
+        return( -1 );
+
+    if( eType != FTDouble && nDecimals != 0 )
+        return( -1 );
+
+    if( nWidth < 1 )
+        return -1;
+
+/* -------------------------------------------------------------------- */
+/*      SfRealloc all the arrays larger to hold the additional field      */
+/*      information.                                                    */
+/* -------------------------------------------------------------------- */
+    psDBF->nFields++;
+
+    psDBF->panFieldOffset = (int *) 
+      SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+
+    psDBF->panFieldSize = (int *) 
+      SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+
+    psDBF->panFieldDecimals = (int *) 
+      SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+
+    psDBF->pachFieldType = (char *) 
+      SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
+
+/* -------------------------------------------------------------------- */
+/*      Assign the new field information fields.                        */
+/* -------------------------------------------------------------------- */
+    psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
+    psDBF->nRecordLength += nWidth;
+    psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
+    psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
+
+    if( eType == FTLogical )
+        psDBF->pachFieldType[psDBF->nFields-1] = 'L';
+    else if( eType == FTString )
+        psDBF->pachFieldType[psDBF->nFields-1] = 'C';
+    else
+        psDBF->pachFieldType[psDBF->nFields-1] = 'N';
+
+/* -------------------------------------------------------------------- */
+/*      Extend the required header information.                         */
+/* -------------------------------------------------------------------- */
+    psDBF->nHeaderLength += 32;
+    psDBF->bUpdated = FALSE;
+
+    psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
+
+    pszFInfo = psDBF->pszHeader + 32 * (psDBF->nFields-1);
+
+    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[psDBF->nFields-1];
+
+    if( eType == FTString )
+    {
+        pszFInfo[16] = (unsigned char) (nWidth % 256);
+        pszFInfo[17] = (unsigned char) (nWidth / 256);
+    }
+    else
+    {
+        pszFInfo[16] = (unsigned char) nWidth;
+        pszFInfo[17] = (unsigned char) nDecimals;
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      Make the current record buffer appropriately larger.            */
+/* -------------------------------------------------------------------- */
+    psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
+					       psDBF->nRecordLength);
+
+    return( psDBF->nFields-1 );
+}
+
+/************************************************************************/
+/*                          DBFReadAttribute()                          */
+/*                                                                      */
+/*      Read one of the attribute fields of a record.                   */
+/************************************************************************/
+
+static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
+                              char chReqType )
+
+{
+    int	       	nRecordOffset;
+    unsigned char	*pabyRec;
+    void	*pReturnField = NULL;
+
+    static double dDoubleField;
+
+/* -------------------------------------------------------------------- */
+/*      Verify selection.                                               */
+/* -------------------------------------------------------------------- */
+    if( hEntity < 0 || hEntity >= psDBF->nRecords )
+        return( NULL );
+
+    if( iField < 0 || iField >= psDBF->nFields )
+        return( NULL );
+
+/* -------------------------------------------------------------------- */
+/*	Have we read the record?					*/
+/* -------------------------------------------------------------------- */
+    if( psDBF->nCurrentRecord != hEntity )
+    {
+	DBFFlushRecord( psDBF );
+
+	nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+	if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 )
+        {
+            fprintf( stderr, "fseek(%d) failed on DBF file.\n",
+                     nRecordOffset );
+            return NULL;
+        }
+
+	if( fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 
+                   1, psDBF->fp ) != 1 )
+        {
+            fprintf( stderr, "fread(%d) failed on DBF file.\n",
+                     psDBF->nRecordLength );
+            return NULL;
+        }
+
+	psDBF->nCurrentRecord = hEntity;
+    }
+
+    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+/* -------------------------------------------------------------------- */
+/*	Ensure our field buffer is large enough to hold this buffer.	*/
+/* -------------------------------------------------------------------- */
+    if( psDBF->panFieldSize[iField]+1 > nStringFieldLen )
+    {
+	nStringFieldLen = psDBF->panFieldSize[iField]*2 + 10;
+	pszStringField = (char *) SfRealloc(pszStringField,nStringFieldLen);
+    }
+
+/* -------------------------------------------------------------------- */
+/*	Extract the requested field.					*/
+/* -------------------------------------------------------------------- */
+    strncpy( pszStringField, 
+	     ((const char *) pabyRec) + psDBF->panFieldOffset[iField],
+	     psDBF->panFieldSize[iField] );
+    pszStringField[psDBF->panFieldSize[iField]] = '\0';
+
+    pReturnField = pszStringField;
+
+/* -------------------------------------------------------------------- */
+/*      Decode the field.                                               */
+/* -------------------------------------------------------------------- */
+    if( chReqType == 'N' )
+    {
+        dDoubleField = (*atof_function)(pszStringField);
+
+	pReturnField = &dDoubleField;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Should we trim white space off the string attribute value?      */
+/* -------------------------------------------------------------------- */
+#ifdef TRIM_DBF_WHITESPACE
+    else
+    {
+        char	*pchSrc, *pchDst;
+
+        pchDst = pchSrc = pszStringField;
+        while( *pchSrc == ' ' )
+            pchSrc++;
+
+        while( *pchSrc != '\0' )
+            *(pchDst++) = *(pchSrc++);
+        *pchDst = '\0';
+
+        while( pchDst != pszStringField && *(--pchDst) == ' ' )
+            *pchDst = '\0';
+    }
+#endif
+    
+    return( pReturnField );
+}
+
+/************************************************************************/
+/*                        DBFReadIntAttribute()                         */
+/*                                                                      */
+/*      Read an integer attribute.                                      */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+    double	*pdValue;
+
+    pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
+
+    if( pdValue == NULL )
+        return 0;
+    else
+        return( (int) *pdValue );
+}
+
+/************************************************************************/
+/*                        DBFReadDoubleAttribute()                      */
+/*                                                                      */
+/*      Read a double attribute.                                        */
+/************************************************************************/
+
+double SHPAPI_CALL
+DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+    double	*pdValue;
+
+    pdValue = (double *) DBFReadAttribute( psDBF, iRecord, iField, 'N' );
+
+    if( pdValue == NULL )
+        return 0.0;
+    else
+        return( *pdValue );
+}
+
+/************************************************************************/
+/*                        DBFReadStringAttribute()                      */
+/*                                                                      */
+/*      Read a string attribute.                                        */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+    return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
+}
+
+/************************************************************************/
+/*                        DBFReadLogicalAttribute()                     */
+/*                                                                      */
+/*      Read a logical attribute.                                       */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+    return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
+}
+
+/************************************************************************/
+/*                         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;
+
+    switch(psDBF->pachFieldType[iField])
+    {
+      case 'N':
+      case 'F':
+        /* NULL numeric fields have value "****************" */
+        return pszValue[0] == '*';
+
+      case 'D':
+        /* NULL date fields have value "00000000" */
+        return strncmp(pszValue,"00000000",8) == 0;
+
+      case 'L':
+        /* NULL boolean fields have value "?" */ 
+        return pszValue[0] == '?';
+
+      default:
+        /* empty string fields are considered NULL */
+        return strlen(pszValue) == 0;
+    }
+}
+
+/************************************************************************/
+/*                          DBFGetFieldCount()                          */
+/*                                                                      */
+/*      Return the number of fields in this table.                      */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetFieldCount( DBFHandle psDBF )
+
+{
+    return( psDBF->nFields );
+}
+
+/************************************************************************/
+/*                         DBFGetRecordCount()                          */
+/*                                                                      */
+/*      Return the number of records in this table.                     */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetRecordCount( DBFHandle psDBF )
+
+{
+    return( psDBF->nRecords );
+}
+
+/************************************************************************/
+/*                          DBFGetFieldInfo()                           */
+/*                                                                      */
+/*      Return any requested information about the field.               */
+/************************************************************************/
+
+DBFFieldType SHPAPI_CALL
+DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
+                 int * pnWidth, int * pnDecimals )
+
+{
+    if( iField < 0 || iField >= psDBF->nFields )
+        return( FTInvalid );
+
+    if( pnWidth != NULL )
+        *pnWidth = psDBF->panFieldSize[iField];
+
+    if( pnDecimals != NULL )
+        *pnDecimals = psDBF->panFieldDecimals[iField];
+
+    if( pszFieldName != NULL )
+    {
+	int	i;
+
+	strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*32, 11 );
+	pszFieldName[11] = '\0';
+	for( i = 10; i > 0 && pszFieldName[i] == ' '; i-- )
+	    pszFieldName[i] = '\0';
+    }
+
+    if ( psDBF->pachFieldType[iField] == 'L' )
+	return( FTLogical);
+
+    else if( psDBF->pachFieldType[iField] == 'N' 
+             || psDBF->pachFieldType[iField] == 'F'
+             || psDBF->pachFieldType[iField] == 'D' )
+    {
+	if( psDBF->panFieldDecimals[iField] > 0 )
+	    return( FTDouble );
+	else
+	    return( FTInteger );
+    }
+    else
+    {
+	return( FTString );
+    }
+}
+
+/************************************************************************/
+/*                         DBFWriteAttribute()                          */
+/*									*/
+/*	Write an attribute record to the file.				*/
+/************************************************************************/
+
+static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
+			     void * pValue )
+
+{
+    int	       	nRecordOffset, i, j, nRetResult = TRUE;
+    unsigned char	*pabyRec;
+    char	szSField[400], szFormat[20];
+
+/* -------------------------------------------------------------------- */
+/*	Is this a valid record?						*/
+/* -------------------------------------------------------------------- */
+    if( hEntity < 0 || hEntity > psDBF->nRecords )
+        return( FALSE );
+
+    if( psDBF->bNoHeader )
+        DBFWriteHeader(psDBF);
+
+/* -------------------------------------------------------------------- */
+/*      Is this a brand new record?                                     */
+/* -------------------------------------------------------------------- */
+    if( hEntity == psDBF->nRecords )
+    {
+	DBFFlushRecord( psDBF );
+
+	psDBF->nRecords++;
+	for( i = 0; i < psDBF->nRecordLength; i++ )
+	    psDBF->pszCurrentRecord[i] = ' ';
+
+	psDBF->nCurrentRecord = hEntity;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Is this an existing record, but different than the last one     */
+/*      we accessed?                                                    */
+/* -------------------------------------------------------------------- */
+    if( psDBF->nCurrentRecord != hEntity )
+    {
+	DBFFlushRecord( psDBF );
+
+	nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+	fseek( psDBF->fp, nRecordOffset, 0 );
+	fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+	psDBF->nCurrentRecord = hEntity;
+    }
+
+    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+    psDBF->bCurrentRecordModified = TRUE;
+    psDBF->bUpdated = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Translate NULL value to valid DBF file representation.          */
+/*                                                                      */
+/*      Contributed by Jim Matthews.                                    */
+/* -------------------------------------------------------------------- */
+    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]), '\0', 
+                    psDBF->panFieldSize[iField] );
+            break;
+        }
+        return TRUE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Assign all the record fields.                                   */
+/* -------------------------------------------------------------------- */
+    switch( psDBF->pachFieldType[iField] )
+    {
+      case 'D':
+      case 'N':
+      case 'F':
+	if( psDBF->panFieldDecimals[iField] == 0 )
+	{
+            int		nWidth = psDBF->panFieldSize[iField];
+
+            if( sizeof(szSField)-2 < nWidth )
+                nWidth = sizeof(szSField)-2;
+
+	    sprintf( szFormat, "%%%dd", nWidth );
+	    sprintf(szSField, szFormat, (int) *((double *) pValue) );
+	    if( (int)strlen(szSField) > psDBF->panFieldSize[iField] )
+            {
+	        szSField[psDBF->panFieldSize[iField]] = '\0';
+                nRetResult = FALSE;
+            }
+
+	    strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+		    szSField, strlen(szSField) );
+	}
+	else
+	{
+            int		nWidth = psDBF->panFieldSize[iField];
+
+            if( sizeof(szSField)-2 < nWidth )
+                nWidth = sizeof(szSField)-2;
+
+	    sprintf( szFormat, "%%%d.%df", 
+                     nWidth, psDBF->panFieldDecimals[iField] );
+	    sprintf(szSField, szFormat, *((double *) pValue) );
+	    if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
+            {
+	        szSField[psDBF->panFieldSize[iField]] = '\0';
+                nRetResult = FALSE;
+            }
+	    strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+		    szSField, strlen(szSField) );
+	}
+	break;
+
+      case 'L':
+        if (psDBF->panFieldSize[iField] >= 1  && 
+            (*(char*)pValue == 'F' || *(char*)pValue == 'T'))
+            *(pabyRec+psDBF->panFieldOffset[iField]) = *(char*)pValue;
+        break;
+
+      default:
+	if( (int) strlen((char *) pValue) > psDBF->panFieldSize[iField] )
+        {
+	    j = psDBF->panFieldSize[iField];
+            nRetResult = FALSE;
+        }
+	else
+        {
+            memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
+                    psDBF->panFieldSize[iField] );
+	    j = strlen((char *) pValue);
+        }
+
+	strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+		(char *) pValue, j );
+	break;
+    }
+
+    return( nRetResult );
+}
+
+/************************************************************************/
+/*                     DBFWriteAttributeDirectly()                      */
+/*                                                                      */
+/*      Write an attribute record to the file, but without any          */
+/*      reformatting based on type.  The provided buffer is written     */
+/*      as is to the field position in the record.                      */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
+                              void * pValue )
+
+{
+    int	       	nRecordOffset, i, j;
+    unsigned char	*pabyRec;
+
+/* -------------------------------------------------------------------- */
+/*	Is this a valid record?						*/
+/* -------------------------------------------------------------------- */
+    if( hEntity < 0 || hEntity > psDBF->nRecords )
+        return( FALSE );
+
+    if( psDBF->bNoHeader )
+        DBFWriteHeader(psDBF);
+
+/* -------------------------------------------------------------------- */
+/*      Is this a brand new record?                                     */
+/* -------------------------------------------------------------------- */
+    if( hEntity == psDBF->nRecords )
+    {
+	DBFFlushRecord( psDBF );
+
+	psDBF->nRecords++;
+	for( i = 0; i < psDBF->nRecordLength; i++ )
+	    psDBF->pszCurrentRecord[i] = ' ';
+
+	psDBF->nCurrentRecord = hEntity;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Is this an existing record, but different than the last one     */
+/*      we accessed?                                                    */
+/* -------------------------------------------------------------------- */
+    if( psDBF->nCurrentRecord != hEntity )
+    {
+	DBFFlushRecord( psDBF );
+
+	nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+	fseek( psDBF->fp, nRecordOffset, 0 );
+	fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+	psDBF->nCurrentRecord = hEntity;
+    }
+
+    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+/* -------------------------------------------------------------------- */
+/*      Assign all the record fields.                                   */
+/* -------------------------------------------------------------------- */
+    if( (int)strlen((char *) pValue) > psDBF->panFieldSize[iField] )
+        j = psDBF->panFieldSize[iField];
+    else
+    {
+        memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
+                psDBF->panFieldSize[iField] );
+        j = strlen((char *) pValue);
+    }
+
+    strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]),
+            (char *) pValue, j );
+
+    psDBF->bCurrentRecordModified = TRUE;
+    psDBF->bUpdated = TRUE;
+
+    return( TRUE );
+}
+
+/************************************************************************/
+/*                      DBFWriteDoubleAttribute()                       */
+/*                                                                      */
+/*      Write a double attribute.                                       */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
+                         double dValue )
+
+{
+    return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
+}
+
+/************************************************************************/
+/*                      DBFWriteIntegerAttribute()                      */
+/*                                                                      */
+/*      Write a integer attribute.                                      */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
+                          int nValue )
+
+{
+    double	dValue = nValue;
+
+    return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) &dValue ) );
+}
+
+/************************************************************************/
+/*                      DBFWriteStringAttribute()                       */
+/*                                                                      */
+/*      Write a string attribute.                                       */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
+                         const char * pszValue )
+
+{
+    return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) pszValue ) );
+}
+
+/************************************************************************/
+/*                      DBFWriteNULLAttribute()                         */
+/*                                                                      */
+/*      Write a string attribute.                                       */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
+
+{
+    return( DBFWriteAttribute( psDBF, iRecord, iField, NULL ) );
+}
+
+/************************************************************************/
+/*                      DBFWriteLogicalAttribute()                      */
+/*                                                                      */
+/*      Write a logical attribute.                                      */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteLogicalAttribute( DBFHandle psDBF, int iRecord, int iField,
+		       const char lValue)
+
+{
+    return( DBFWriteAttribute( psDBF, iRecord, iField, (void *) (&lValue) ) );
+}
+
+/************************************************************************/
+/*                         DBFWriteTuple()                              */
+/*									*/
+/*	Write an attribute record to the file.				*/
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
+
+{
+    int	       	nRecordOffset, i;
+    unsigned char	*pabyRec;
+
+/* -------------------------------------------------------------------- */
+/*	Is this a valid record?						*/
+/* -------------------------------------------------------------------- */
+    if( hEntity < 0 || hEntity > psDBF->nRecords )
+        return( FALSE );
+
+    if( psDBF->bNoHeader )
+        DBFWriteHeader(psDBF);
+
+/* -------------------------------------------------------------------- */
+/*      Is this a brand new record?                                     */
+/* -------------------------------------------------------------------- */
+    if( hEntity == psDBF->nRecords )
+    {
+	DBFFlushRecord( psDBF );
+
+	psDBF->nRecords++;
+	for( i = 0; i < psDBF->nRecordLength; i++ )
+	    psDBF->pszCurrentRecord[i] = ' ';
+
+	psDBF->nCurrentRecord = hEntity;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Is this an existing record, but different than the last one     */
+/*      we accessed?                                                    */
+/* -------------------------------------------------------------------- */
+    if( psDBF->nCurrentRecord != hEntity )
+    {
+	DBFFlushRecord( psDBF );
+
+	nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+	fseek( psDBF->fp, nRecordOffset, 0 );
+	fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+	psDBF->nCurrentRecord = hEntity;
+    }
+
+    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+    memcpy ( pabyRec, pRawTuple,  psDBF->nRecordLength );
+
+    psDBF->bCurrentRecordModified = TRUE;
+    psDBF->bUpdated = TRUE;
+
+    return( TRUE );
+}
+
+/************************************************************************/
+/*                          DBFReadTuple()                              */
+/*                                                                      */
+/*      Read one of the attribute fields of a record.                   */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+DBFReadTuple(DBFHandle psDBF, int hEntity )
+
+{
+    int	       	nRecordOffset;
+    unsigned char	*pabyRec;
+    static char	*pReturnTuple = NULL;
+
+    static int	nTupleLen = 0;
+
+/* -------------------------------------------------------------------- */
+/*	Have we read the record?					*/
+/* -------------------------------------------------------------------- */
+    if( hEntity < 0 || hEntity >= psDBF->nRecords )
+        return( NULL );
+
+    if( psDBF->nCurrentRecord != hEntity )
+    {
+	DBFFlushRecord( psDBF );
+
+	nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
+
+	fseek( psDBF->fp, nRecordOffset, 0 );
+	fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+	psDBF->nCurrentRecord = hEntity;
+    }
+
+    pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
+
+    if ( nTupleLen < psDBF->nRecordLength) {
+      nTupleLen = psDBF->nRecordLength;
+      pReturnTuple = (char *) SfRealloc(pReturnTuple, psDBF->nRecordLength);
+    }
+    
+    memcpy ( pReturnTuple, pabyRec, psDBF->nRecordLength );
+        
+    return( pReturnTuple );
+}
+
+/************************************************************************/
+/*                          DBFCloneEmpty()                              */
+/*                                                                      */
+/*      Read one of the attribute fields of a record.                   */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename ) 
+{
+    DBFHandle	newDBF;
+
+   newDBF = DBFCreate ( pszFilename );
+   if ( newDBF == NULL ) return ( NULL ); 
+   
+   newDBF->pszHeader = (char *) malloc ( 32 * psDBF->nFields );
+   memcpy ( newDBF->pszHeader, psDBF->pszHeader, 32 * psDBF->nFields );
+   
+   newDBF->nFields = psDBF->nFields;
+   newDBF->nRecordLength = psDBF->nRecordLength;
+   newDBF->nHeaderLength = 32 * (psDBF->nFields+1);
+    
+   newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields ); 
+   memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
+   newDBF->panFieldSize = (int *) malloc ( sizeof(int) * psDBF->nFields );
+   memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
+   newDBF->panFieldDecimals = (int *) malloc ( sizeof(int) * psDBF->nFields );
+   memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
+   newDBF->pachFieldType = (char *) malloc ( sizeof(int) * psDBF->nFields );
+   memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(int) * psDBF->nFields );
+
+   newDBF->bNoHeader = TRUE;
+   newDBF->bUpdated = TRUE;
+   
+   DBFWriteHeader ( newDBF );
+   DBFClose ( newDBF );
+   
+   newDBF = DBFOpen ( pszFilename, "rb+" );
+
+   return ( newDBF );
+}
+
+/************************************************************************/
+/*                       DBFGetNativeFieldType()                        */
+/*                                                                      */
+/*      Return the DBase field type for the specified field.            */
+/*                                                                      */
+/*      Value can be one of: 'C' (String), 'D' (Date), 'F' (Float),     */
+/*                           'N' (Numeric, with or without decimal),    */
+/*                           'L' (Logical),                             */
+/*                           'M' (Memo: 10 digits .DBT block ptr)       */
+/************************************************************************/
+
+char SHPAPI_CALL
+DBFGetNativeFieldType( DBFHandle psDBF, int iField )
+
+{
+    if( iField >=0 && iField < psDBF->nFields )
+        return psDBF->pachFieldType[iField];
+
+    return  ' ';
+}
+
+/************************************************************************/
+/*                            str_to_upper()                            */
+/************************************************************************/
+
+static void str_to_upper (char *string)
+{
+    int len;
+    short i = -1;
+
+    len = strlen (string);
+
+    while (++i < len)
+        if (isalpha(string[i]) && islower(string[i]))
+            string[i] = (char) toupper ((int)string[i]);
+}
+
+/************************************************************************/
+/*                          DBFGetFieldIndex()                          */
+/*                                                                      */
+/*      Get the index number for a field in a .dbf file.                */
+/*                                                                      */
+/*      Contributed by Jim Matthews.                                    */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
+
+{
+    char          name[12], name1[12], name2[12];
+    int           i;
+
+    strncpy(name1, pszFieldName,11);
+    name1[11] = '\0';
+    str_to_upper(name1);
+
+    for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
+    {
+        DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
+        strncpy(name2,name,11);
+        str_to_upper(name2);
+
+        if(!strncmp(name1,name2,10))
+            return(i);
+    }
+    return(-1);
+}

Added: packages/thuban/branches/upstream/current/libraries/shapelib/shapefil.h
===================================================================
--- packages/thuban/branches/upstream/current/libraries/shapelib/shapefil.h	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/shapelib/shapefil.h	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,539 @@
+#ifndef _SHAPEFILE_H_INCLUDED
+#define _SHAPEFILE_H_INCLUDED
+
+/******************************************************************************
+ * $Id: shapefil.h 2703 2006-09-24 18:51:39Z bernhard $
+ *
+ * Project:  Shapelib
+ * Purpose:  Primary include file for Shapelib.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log$
+ * Revision 1.3  2004/05/17 15:47:57  bh
+ * Update to newest shapelib and get rid of Thuban specific extensions,
+ * i.e. use the new DBFUpdateHeader instead of our DBFCommit kludge
+ *
+ * * libraries/shapelib/shpopen.c: Update to version from current
+ * shapelib CVS.
+ *
+ * * libraries/shapelib/shapefil.h: Update to version from current
+ * shapelib CVS.
+ *
+ * * libraries/shapelib/dbfopen.c: Update to version from current
+ * shapelib CVS.
+ * (DBFCommit): Effectively removed since shapelib itself has
+ * DBFUpdateHeader now which is better for what DBFCommit wanted to
+ * achieve.
+ * We're now using an unmodified version of dbfopen.
+ *
+ * * libraries/pyshapelib/dbflib_wrap.c, libraries/pyshapelib/dbflib.py:
+ * Update from dbflib.i
+ *
+ * * libraries/pyshapelib/dbflib.i (DBFInfo_commit): New. Implementation of
+ * the commit method.  This new indirection is necessary because we use the
+ * DBFUpdateHeader function now which is not available in shapelib <=
+ * 1.2.10
+ * (DBFFile::commit): Use DBFInfo_commit as implementation
+ * (pragma __class__): New. Kludge to remove the commit method when
+ * the DBFUpdateHeader function isn't available
+ * (_have_commit): New. Helper for the pragma kludge.
+ *
+ * * libraries/pyshapelib/setup.py (dbf_macros): New. Return the
+ * preprocessor macros needed to compile the dbflib wrapper.  Determine
+ * whether DBFUpdateHeader is available and define the right value of
+ * HAVE_UPDATE_HEADER
+ * (extensions): Use dbf_macros for the dbflibc extension
+ *
+ * * setup.py (extensions): Add the HAVE_UPDATE_HEADER macro with
+ * value '1' to the Lib.dbflibc extension.  This simply reflects the
+ * shapelib and pyshapelib updates
+ *
+ * Revision 1.28  2003/12/29 06:02:18  fwarmerdam
+ * added cpl_error.h option
+ *
+ * Revision 1.27  2003/04/21 18:30:37  warmerda
+ * added header write/update public methods
+ *
+ * Revision 1.26  2002/09/29 00:00:08  warmerda
+ * added FTLogical and logical attribute read/write calls
+ *
+ * Revision 1.25  2002/05/07 13:46:30  warmerda
+ * added DBFWriteAttributeDirectly().
+ *
+ * Revision 1.24  2002/04/10 16:59:54  warmerda
+ * added SHPRewindObject
+ *
+ * Revision 1.23  2002/01/15 14:36:07  warmerda
+ * updated email address
+ *
+ * Revision 1.22  2002/01/15 14:32:00  warmerda
+ * try to improve SHPAPI_CALL docs
+ *
+ * Revision 1.21  2001/11/01 16:29:55  warmerda
+ * move pabyRec into SHPInfo for thread safety
+ *
+ * Revision 1.20  2001/07/20 13:06:02  warmerda
+ * fixed SHPAPI attribute for SHPTreeFindLikelyShapes
+ *
+ * Revision 1.19  2001/05/31 19:20:13  warmerda
+ * added DBFGetFieldIndex()
+ *
+ * Revision 1.18  2001/05/31 18:15:40  warmerda
+ * Added support for NULL fields in DBF files
+ *
+ * Revision 1.17  2001/05/23 13:36:52  warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.16  2000/09/25 14:15:59  warmerda
+ * added DBFGetNativeFieldType()
+ *
+ * Revision 1.15  2000/02/16 16:03:51  warmerda
+ * added null shape support
+ *
+ * Revision 1.14  1999/11/05 14:12:05  warmerda
+ * updated license terms
+ *
+ * Revision 1.13  1999/06/02 18:24:21  warmerda
+ * added trimming code
+ *
+ * Revision 1.12  1999/06/02 17:56:12  warmerda
+ * added quad'' subnode support for trees
+ *
+ * Revision 1.11  1999/05/18 19:11:11  warmerda
+ * Added example searching capability
+ *
+ * Revision 1.10  1999/05/18 17:49:38  warmerda
+ * added initial quadtree support
+ *
+ * Revision 1.9  1999/05/11 03:19:28  warmerda
+ * added new Tuple api, and improved extension handling - add from candrsn
+ *
+ * Revision 1.8  1999/03/23 17:22:27  warmerda
+ * Added extern "C" protection for C++ users of shapefil.h.
+ *
+ * Revision 1.7  1998/12/31 15:31:07  warmerda
+ * Added the TRIM_DBF_WHITESPACE and DISABLE_MULTIPATCH_MEASURE options.
+ *
+ * Revision 1.6  1998/12/03 15:48:15  warmerda
+ * Added SHPCalculateExtents().
+ *
+ * Revision 1.5  1998/11/09 20:57:16  warmerda
+ * Altered SHPGetInfo() call.
+ *
+ * Revision 1.4  1998/11/09 20:19:33  warmerda
+ * Added 3D support, and use of SHPObject.
+ *
+ * Revision 1.3  1995/08/23 02:24:05  warmerda
+ * Added support for reading bounds.
+ *
+ * Revision 1.2  1995/08/04  03:17:39  warmerda
+ * Added header.
+ *
+ */
+
+#include <stdio.h>
+
+#ifdef USE_DBMALLOC
+#include <dbmalloc.h>
+#endif
+
+#ifdef USE_CPL
+#include "cpl_error.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/************************************************************************/
+/*                        Configuration options.                        */
+/************************************************************************/
+
+/* -------------------------------------------------------------------- */
+/*      Should the DBFReadStringAttribute() strip leading and           */
+/*      trailing white space?                                           */
+/* -------------------------------------------------------------------- */
+#define TRIM_DBF_WHITESPACE
+
+/* -------------------------------------------------------------------- */
+/*      Should we write measure values to the Multipatch object?        */
+/*      Reportedly ArcView crashes if we do write it, so for now it     */
+/*      is disabled.                                                    */
+/* -------------------------------------------------------------------- */
+#define DISABLE_MULTIPATCH_MEASURE
+
+/* -------------------------------------------------------------------- */
+/*      SHPAPI_CALL                                                     */
+/*                                                                      */
+/*      The following two macros are present to allow forcing           */
+/*      various calling conventions on the Shapelib API.                */
+/*                                                                      */
+/*      To force __stdcall conventions (needed to call Shapelib         */
+/*      from Visual Basic and/or Dephi I believe) the makefile could    */
+/*      be modified to define:                                          */
+/*                                                                      */
+/*        /DSHPAPI_CALL=__stdcall                                       */
+/*                                                                      */
+/*      If it is desired to force export of the Shapelib API without    */
+/*      using the shapelib.def file, use the following definition.      */
+/*                                                                      */
+/*        /DSHAPELIB_DLLEXPORT                                          */
+/*                                                                      */
+/*      To get both at once it will be necessary to hack this           */
+/*      include file to define:                                         */
+/*                                                                      */
+/*        #define SHPAPI_CALL __declspec(dllexport) __stdcall           */
+/*        #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall        */
+/*                                                                      */
+/*      The complexity of the situtation is partly caused by the        */
+/*      peculiar requirement of Visual C++ that __stdcall appear        */
+/*      after any "*"'s in the return value of a function while the     */
+/*      __declspec(dllexport) must appear before them.                  */
+/* -------------------------------------------------------------------- */
+
+#ifdef SHAPELIB_DLLEXPORT
+#  define SHPAPI_CALL __declspec(dllexport)
+#  define SHPAPI_CALL1(x)  __declspec(dllexport) x
+#endif
+
+#ifndef SHPAPI_CALL
+#  define SHPAPI_CALL
+#endif
+
+#ifndef SHPAPI_CALL1
+#  define SHPAPI_CALL1(x)      x SHPAPI_CALL
+#endif
+    
+/************************************************************************/
+/*                             SHP Support.                             */
+/************************************************************************/
+typedef	struct
+{
+    FILE        *fpSHP;
+    FILE	*fpSHX;
+
+    int		nShapeType;				/* SHPT_* */
+    
+    int		nFileSize;				/* SHP file */
+
+    int         nRecords;
+    int		nMaxRecords;
+    int		*panRecOffset;
+    int		*panRecSize;
+
+    double	adBoundsMin[4];
+    double	adBoundsMax[4];
+
+    int		bUpdated;
+
+    unsigned char *pabyRec;
+    int         nBufSize;
+} SHPInfo;
+
+typedef SHPInfo * SHPHandle;
+
+/* -------------------------------------------------------------------- */
+/*      Shape types (nSHPType)                                          */
+/* -------------------------------------------------------------------- */
+#define SHPT_NULL	0
+#define SHPT_POINT	1
+#define SHPT_ARC	3
+#define SHPT_POLYGON	5
+#define SHPT_MULTIPOINT	8
+#define SHPT_POINTZ	11
+#define SHPT_ARCZ	13
+#define SHPT_POLYGONZ	15
+#define SHPT_MULTIPOINTZ 18
+#define SHPT_POINTM	21
+#define SHPT_ARCM	23
+#define SHPT_POLYGONM	25
+#define SHPT_MULTIPOINTM 28
+#define SHPT_MULTIPATCH 31
+
+
+/* -------------------------------------------------------------------- */
+/*      Part types - everything but SHPT_MULTIPATCH just uses           */
+/*      SHPP_RING.                                                      */
+/* -------------------------------------------------------------------- */
+
+#define SHPP_TRISTRIP	0
+#define SHPP_TRIFAN	1
+#define SHPP_OUTERRING	2
+#define SHPP_INNERRING	3
+#define SHPP_FIRSTRING	4
+#define SHPP_RING	5
+
+/* -------------------------------------------------------------------- */
+/*      SHPObject - represents on shape (without attributes) read       */
+/*      from the .shp file.                                             */
+/* -------------------------------------------------------------------- */
+typedef struct
+{
+    int		nSHPType;
+
+    int		nShapeId; /* -1 is unknown/unassigned */
+
+    int		nParts;
+    int		*panPartStart;
+    int		*panPartType;
+    
+    int		nVertices;
+    double	*padfX;
+    double	*padfY;
+    double	*padfZ;
+    double	*padfM;
+
+    double	dfXMin;
+    double	dfYMin;
+    double	dfZMin;
+    double	dfMMin;
+
+    double	dfXMax;
+    double	dfYMax;
+    double	dfZMax;
+    double	dfMMax;
+} SHPObject;
+
+/* -------------------------------------------------------------------- */
+/*      SHP API Prototypes                                              */
+/* -------------------------------------------------------------------- */
+SHPHandle SHPAPI_CALL
+      SHPOpen( const char * pszShapeFile, const char * pszAccess );
+SHPHandle SHPAPI_CALL
+      SHPCreate( const char * pszShapeFile, int nShapeType );
+void SHPAPI_CALL
+      SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
+                  double * padfMinBound, double * padfMaxBound );
+
+SHPObject SHPAPI_CALL1(*)
+      SHPReadObject( SHPHandle hSHP, int iShape );
+int SHPAPI_CALL
+      SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
+
+void SHPAPI_CALL
+      SHPDestroyObject( SHPObject * psObject );
+void SHPAPI_CALL
+      SHPComputeExtents( SHPObject * psObject );
+SHPObject SHPAPI_CALL1(*)
+      SHPCreateObject( int nSHPType, int nShapeId,
+                       int nParts, int * panPartStart, int * panPartType,
+                       int nVertices, double * padfX, double * padfY,
+                       double * padfZ, double * padfM );
+SHPObject SHPAPI_CALL1(*)
+      SHPCreateSimpleObject( int nSHPType, int nVertices,
+                             double * padfX, double * padfY, double * padfZ );
+
+int SHPAPI_CALL
+      SHPRewindObject( SHPHandle hSHP, SHPObject * psObject );
+
+void SHPAPI_CALL SHPClose( SHPHandle hSHP );
+void SHPAPI_CALL SHPWriteHeader( SHPHandle hSHP );
+
+const char SHPAPI_CALL1(*)
+      SHPTypeName( int nSHPType );
+const char SHPAPI_CALL1(*)
+      SHPPartTypeName( int nPartType );
+
+/* -------------------------------------------------------------------- */
+/*      Shape quadtree indexing API.                                    */
+/* -------------------------------------------------------------------- */
+
+/* this can be two or four for binary or quad tree */
+#define MAX_SUBNODE	4
+
+typedef struct shape_tree_node
+{
+    /* region covered by this node */
+    double	adfBoundsMin[4];
+    double	adfBoundsMax[4];
+
+    /* list of shapes stored at this node.  The papsShapeObj pointers
+       or the whole list can be NULL */
+    int		nShapeCount;
+    int		*panShapeIds;
+    SHPObject   **papsShapeObj;
+
+    int		nSubNodes;
+    struct shape_tree_node *apsSubNode[MAX_SUBNODE];
+    
+} SHPTreeNode;
+
+typedef struct
+{
+    SHPHandle   hSHP;
+    
+    int		nMaxDepth;
+    int		nDimension;
+    
+    SHPTreeNode	*psRoot;
+} SHPTree;
+
+SHPTree SHPAPI_CALL1(*)
+      SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
+                     double *padfBoundsMin, double *padfBoundsMax );
+void    SHPAPI_CALL
+      SHPDestroyTree( SHPTree * hTree );
+
+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 );
+
+void 	SHPAPI_CALL
+      SHPTreeTrimExtraNodes( SHPTree * hTree );
+
+int    SHPAPI_CALL1(*)
+      SHPTreeFindLikelyShapes( SHPTree * hTree,
+                               double * padfBoundsMin,
+                               double * padfBoundsMax,
+                               int * );
+int     SHPAPI_CALL
+      SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
+
+/************************************************************************/
+/*                             DBF Support.                             */
+/************************************************************************/
+typedef	struct
+{
+    FILE	*fp;
+
+    int         nRecords;
+
+    int		nRecordLength;
+    int		nHeaderLength;
+    int		nFields;
+    int		*panFieldOffset;
+    int		*panFieldSize;
+    int		*panFieldDecimals;
+    char	*pachFieldType;
+
+    char	*pszHeader;
+
+    int		nCurrentRecord;
+    int		bCurrentRecordModified;
+    char	*pszCurrentRecord;
+    
+    int		bNoHeader;
+    int		bUpdated;
+} DBFInfo;
+
+typedef DBFInfo * DBFHandle;
+
+typedef enum {
+  FTString,
+  FTInteger,
+  FTDouble,
+  FTLogical,
+  FTInvalid
+} DBFFieldType;
+
+#define XBASE_FLDHDR_SZ       32
+
+/* to hand over a locale agnostic atof function, if decimal_point != ".\0" */
+void SHPAPI_CALL
+	DBFSetatof_function(  double (* new_atof_function)(const char *nptr));
+
+DBFHandle SHPAPI_CALL
+      DBFOpen( const char * pszDBFFile, const char * pszAccess );
+DBFHandle SHPAPI_CALL
+      DBFCreate( const char * pszDBFFile );
+
+int	SHPAPI_CALL
+      DBFGetFieldCount( DBFHandle psDBF );
+int	SHPAPI_CALL
+      DBFGetRecordCount( DBFHandle psDBF );
+int	SHPAPI_CALL
+      DBFAddField( DBFHandle hDBF, const char * pszFieldName,
+                   DBFFieldType eType, int nWidth, int nDecimals );
+
+DBFFieldType SHPAPI_CALL
+      DBFGetFieldInfo( DBFHandle psDBF, int iField, 
+                       char * pszFieldName, int * pnWidth, int * pnDecimals );
+
+int SHPAPI_CALL
+      DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
+
+int 	SHPAPI_CALL
+      DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
+double 	SHPAPI_CALL
+      DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
+const char SHPAPI_CALL1(*)
+      DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
+const char SHPAPI_CALL1(*)
+      DBFReadLogicalAttribute( DBFHandle hDBF, int iShape, int iField );
+int     SHPAPI_CALL
+      DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
+
+int SHPAPI_CALL
+      DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField, 
+                                int nFieldValue );
+int SHPAPI_CALL
+      DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
+                               double dFieldValue );
+int SHPAPI_CALL
+      DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
+                               const char * pszFieldValue );
+int SHPAPI_CALL
+     DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
+
+int SHPAPI_CALL
+     DBFWriteLogicalAttribute( DBFHandle hDBF, int iShape, int iField,
+			       const char lFieldValue);
+int SHPAPI_CALL
+     DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
+                               void * pValue );
+const char SHPAPI_CALL1(*)
+      DBFReadTuple(DBFHandle psDBF, int hEntity );
+int SHPAPI_CALL
+      DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
+
+DBFHandle SHPAPI_CALL
+      DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
+ 
+void	SHPAPI_CALL
+      DBFClose( DBFHandle hDBF );
+void    SHPAPI_CALL
+      DBFUpdateHeader( DBFHandle hDBF );
+char    SHPAPI_CALL
+      DBFGetNativeFieldType( DBFHandle hDBF, int iField );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ndef _SHAPEFILE_H_INCLUDED */

Added: packages/thuban/branches/upstream/current/libraries/shapelib/shpopen.c
===================================================================
--- packages/thuban/branches/upstream/current/libraries/shapelib/shpopen.c	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/shapelib/shpopen.c	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,2035 @@
+/******************************************************************************
+ * $Id: shpopen.c 2212 2004-05-17 15:47:57Z bh $
+ *
+ * Project:  Shapelib
+ * Purpose:  Implementation of core Shapefile read/write functions.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, 2001, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log$
+ * Revision 1.3  2004/05/17 15:47:57  bh
+ * Update to newest shapelib and get rid of Thuban specific extensions,
+ * i.e. use the new DBFUpdateHeader instead of our DBFCommit kludge
+ *
+ * * libraries/shapelib/shpopen.c: Update to version from current
+ * shapelib CVS.
+ *
+ * * libraries/shapelib/shapefil.h: Update to version from current
+ * shapelib CVS.
+ *
+ * * libraries/shapelib/dbfopen.c: Update to version from current
+ * shapelib CVS.
+ * (DBFCommit): Effectively removed since shapelib itself has
+ * DBFUpdateHeader now which is better for what DBFCommit wanted to
+ * achieve.
+ * We're now using an unmodified version of dbfopen.
+ *
+ * * libraries/pyshapelib/dbflib_wrap.c, libraries/pyshapelib/dbflib.py:
+ * Update from dbflib.i
+ *
+ * * libraries/pyshapelib/dbflib.i (DBFInfo_commit): New. Implementation of
+ * the commit method.  This new indirection is necessary because we use the
+ * DBFUpdateHeader function now which is not available in shapelib <=
+ * 1.2.10
+ * (DBFFile::commit): Use DBFInfo_commit as implementation
+ * (pragma __class__): New. Kludge to remove the commit method when
+ * the DBFUpdateHeader function isn't available
+ * (_have_commit): New. Helper for the pragma kludge.
+ *
+ * * libraries/pyshapelib/setup.py (dbf_macros): New. Return the
+ * preprocessor macros needed to compile the dbflib wrapper.  Determine
+ * whether DBFUpdateHeader is available and define the right value of
+ * HAVE_UPDATE_HEADER
+ * (extensions): Use dbf_macros for the dbflibc extension
+ *
+ * * setup.py (extensions): Add the HAVE_UPDATE_HEADER macro with
+ * value '1' to the Lib.dbflibc extension.  This simply reflects the
+ * shapelib and pyshapelib updates
+ *
+ * Revision 1.44  2003/12/29 00:18:39  fwarmerdam
+ * added error checking for failed IO and optional CPL error reporting
+ *
+ * Revision 1.43  2003/12/01 16:20:08  warmerda
+ * be careful of zero vertex shapes
+ *
+ * Revision 1.42  2003/12/01 14:58:27  warmerda
+ * added degenerate object check in SHPRewindObject()
+ *
+ * Revision 1.41  2003/07/08 15:22:43  warmerda
+ * avoid warning
+ *
+ * Revision 1.40  2003/04/21 18:30:37  warmerda
+ * added header write/update public methods
+ *
+ * Revision 1.39  2002/08/26 06:46:56  warmerda
+ * avoid c++ comments
+ *
+ * Revision 1.38  2002/05/07 16:43:39  warmerda
+ * Removed debugging printf.
+ *
+ * Revision 1.37  2002/04/10 17:35:22  warmerda
+ * fixed bug in ring reversal code
+ *
+ * Revision 1.36  2002/04/10 16:59:54  warmerda
+ * added SHPRewindObject
+ *
+ * Revision 1.35  2001/12/07 15:10:44  warmerda
+ * fix if .shx fails to open
+ *
+ * Revision 1.34  2001/11/01 16:29:55  warmerda
+ * move pabyRec into SHPInfo for thread safety
+ *
+ * Revision 1.33  2001/07/03 12:18:15  warmerda
+ * Improved cleanup if SHX not found, provied by Riccardo Cohen.
+ *
+ * Revision 1.32  2001/06/22 01:58:07  warmerda
+ * be more careful about establishing initial bounds in face of NULL shapes
+ *
+ * Revision 1.31  2001/05/31 19:35:29  warmerda
+ * added support for writing null shapes
+ *
+ * Revision 1.30  2001/05/28 12:46:29  warmerda
+ * Add some checking on reasonableness of record count when opening.
+ *
+ * Revision 1.29  2001/05/23 13:36:52  warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.28  2001/02/06 22:25:06  warmerda
+ * fixed memory leaks when SHPOpen() fails
+ *
+ * Revision 1.27  2000/07/18 15:21:33  warmerda
+ * added better enforcement of -1 for append in SHPWriteObject
+ *
+ * Revision 1.26  2000/02/16 16:03:51  warmerda
+ * added null shape support
+ *
+ * Revision 1.25  1999/12/15 13:47:07  warmerda
+ * Fixed record size settings in .shp file (was 4 words too long)
+ * Added stdlib.h.
+ *
+ * Revision 1.24  1999/11/05 14:12:04  warmerda
+ * updated license terms
+ *
+ * Revision 1.23  1999/07/27 00:53:46  warmerda
+ * added support for rewriting shapes
+ *
+ * Revision 1.22  1999/06/11 19:19:11  warmerda
+ * Cleanup pabyRec static buffer on SHPClose().
+ *
+ * Revision 1.21  1999/06/02 14:57:56  kshih
+ * Remove unused variables
+ *
+ * Revision 1.20  1999/04/19 21:04:17  warmerda
+ * Fixed syntax error.
+ *
+ * Revision 1.19  1999/04/19 21:01:57  warmerda
+ * Force access string to binary in SHPOpen().
+ *
+ * Revision 1.18  1999/04/01 18:48:07  warmerda
+ * Try upper case extensions if lower case doesn't work.
+ *
+ * Revision 1.17  1998/12/31 15:29:39  warmerda
+ * Disable writing measure values to multipatch objects if
+ * DISABLE_MULTIPATCH_MEASURE is defined.
+ *
+ * Revision 1.16  1998/12/16 05:14:33  warmerda
+ * Added support to write MULTIPATCH.  Fixed reading Z coordinate of
+ * MULTIPATCH. Fixed record size written for all feature types.
+ *
+ * Revision 1.15  1998/12/03 16:35:29  warmerda
+ * r+b is proper binary access string, not rb+.
+ *
+ * Revision 1.14  1998/12/03 15:47:56  warmerda
+ * Fixed setting of nVertices in SHPCreateObject().
+ *
+ * Revision 1.13  1998/12/03 15:33:54  warmerda
+ * Made SHPCalculateExtents() separately callable.
+ *
+ * Revision 1.12  1998/11/11 20:01:50  warmerda
+ * Fixed bug writing ArcM/Z, and PolygonM/Z for big endian machines.
+ *
+ * Revision 1.11  1998/11/09 20:56:44  warmerda
+ * Fixed up handling of file wide bounds.
+ *
+ * Revision 1.10  1998/11/09 20:18:51  warmerda
+ * Converted to support 3D shapefiles, and use of SHPObject.
+ *
+ * Revision 1.9  1998/02/24 15:09:05  warmerda
+ * Fixed memory leak.
+ *
+ * Revision 1.8  1997/12/04 15:40:29  warmerda
+ * Fixed byte swapping of record number, and record length fields in the
+ * .shp file.
+ *
+ * Revision 1.7  1995/10/21 03:15:58  warmerda
+ * Added support for binary file access, the magic cookie 9997
+ * and tried to improve the int32 selection logic for 16bit systems.
+ *
+ * Revision 1.6  1995/09/04  04:19:41  warmerda
+ * Added fix for file bounds.
+ *
+ * Revision 1.5  1995/08/25  15:16:44  warmerda
+ * Fixed a couple of problems with big endian systems ... one with bounds
+ * and the other with multipart polygons.
+ *
+ * Revision 1.4  1995/08/24  18:10:17  warmerda
+ * Switch to use SfRealloc() to avoid problems with pre-ANSI realloc()
+ * functions (such as on the Sun).
+ *
+ * Revision 1.3  1995/08/23  02:23:15  warmerda
+ * Added support for reading bounds, and fixed up problems in setting the
+ * file wide bounds.
+ *
+ * Revision 1.2  1995/08/04  03:16:57  warmerda
+ * Added header.
+ *
+ */
+
+static char rcsid[] = 
+  "$Id: shpopen.c 2212 2004-05-17 15:47:57Z bh $";
+
+#include "shapefil.h"
+
+#include <math.h>
+#include <limits.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef unsigned char uchar;
+
+#if UINT_MAX == 65535
+typedef long	      int32;
+#else
+typedef int	      int32;
+#endif
+
+#ifndef FALSE
+#  define FALSE		0
+#  define TRUE		1
+#endif
+
+#define ByteCopy( a, b, c )	memcpy( b, a, c )
+#ifndef MAX
+#  define MIN(a,b)      ((a<b) ? a : b)
+#  define MAX(a,b)      ((a>b) ? a : b)
+#endif
+
+static int 	bBigEndian;
+
+
+/************************************************************************/
+/*                              SwapWord()                              */
+/*                                                                      */
+/*      Swap a 2, 4 or 8 byte word.                                     */
+/************************************************************************/
+
+static void	SwapWord( int length, void * wordP )
+
+{
+    int		i;
+    uchar	temp;
+
+    for( i=0; i < length/2; i++ )
+    {
+	temp = ((uchar *) wordP)[i];
+	((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1];
+	((uchar *) wordP)[length-i-1] = temp;
+    }
+}
+
+/************************************************************************/
+/*                             SfRealloc()                              */
+/*                                                                      */
+/*      A realloc cover function that will access a NULL pointer as     */
+/*      a valid input.                                                  */
+/************************************************************************/
+
+static void * SfRealloc( void * pMem, int nNewSize )
+
+{
+    if( pMem == NULL )
+        return( (void *) malloc(nNewSize) );
+    else
+        return( (void *) realloc(pMem,nNewSize) );
+}
+
+/************************************************************************/
+/*                          SHPWriteHeader()                            */
+/*                                                                      */
+/*      Write out a header for the .shp and .shx files as well as the	*/
+/*	contents of the index (.shx) file.				*/
+/************************************************************************/
+
+void SHPWriteHeader( SHPHandle psSHP )
+
+{
+    uchar     	abyHeader[100];
+    int		i;
+    int32	i32;
+    double	dValue;
+    int32	*panSHX;
+
+/* -------------------------------------------------------------------- */
+/*      Prepare header block for .shp file.                             */
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < 100; i++ )
+      abyHeader[i] = 0;
+
+    abyHeader[2] = 0x27;				/* magic cookie */
+    abyHeader[3] = 0x0a;
+
+    i32 = psSHP->nFileSize/2;				/* file size */
+    ByteCopy( &i32, abyHeader+24, 4 );
+    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+    
+    i32 = 1000;						/* version */
+    ByteCopy( &i32, abyHeader+28, 4 );
+    if( bBigEndian ) SwapWord( 4, abyHeader+28 );
+    
+    i32 = psSHP->nShapeType;				/* shape type */
+    ByteCopy( &i32, abyHeader+32, 4 );
+    if( bBigEndian ) SwapWord( 4, abyHeader+32 );
+
+    dValue = psSHP->adBoundsMin[0];			/* set bounds */
+    ByteCopy( &dValue, abyHeader+36, 8 );
+    if( bBigEndian ) SwapWord( 8, abyHeader+36 );
+
+    dValue = psSHP->adBoundsMin[1];
+    ByteCopy( &dValue, abyHeader+44, 8 );
+    if( bBigEndian ) SwapWord( 8, abyHeader+44 );
+
+    dValue = psSHP->adBoundsMax[0];
+    ByteCopy( &dValue, abyHeader+52, 8 );
+    if( bBigEndian ) SwapWord( 8, abyHeader+52 );
+
+    dValue = psSHP->adBoundsMax[1];
+    ByteCopy( &dValue, abyHeader+60, 8 );
+    if( bBigEndian ) SwapWord( 8, abyHeader+60 );
+
+    dValue = psSHP->adBoundsMin[2];			/* z */
+    ByteCopy( &dValue, abyHeader+68, 8 );
+    if( bBigEndian ) SwapWord( 8, abyHeader+68 );
+
+    dValue = psSHP->adBoundsMax[2];
+    ByteCopy( &dValue, abyHeader+76, 8 );
+    if( bBigEndian ) SwapWord( 8, abyHeader+76 );
+
+    dValue = psSHP->adBoundsMin[3];			/* m */
+    ByteCopy( &dValue, abyHeader+84, 8 );
+    if( bBigEndian ) SwapWord( 8, abyHeader+84 );
+
+    dValue = psSHP->adBoundsMax[3];
+    ByteCopy( &dValue, abyHeader+92, 8 );
+    if( bBigEndian ) SwapWord( 8, abyHeader+92 );
+
+/* -------------------------------------------------------------------- */
+/*      Write .shp file header.                                         */
+/* -------------------------------------------------------------------- */
+    if( fseek( psSHP->fpSHP, 0, 0 ) != 0 
+        || fwrite( abyHeader, 100, 1, psSHP->fpSHP ) != 1 )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "Failure writing .shp header." );
+#endif
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Prepare, and write .shx file header.                            */
+/* -------------------------------------------------------------------- */
+    i32 = (psSHP->nRecords * 2 * sizeof(int32) + 100)/2;   /* file size */
+    ByteCopy( &i32, abyHeader+24, 4 );
+    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+    
+    if( fseek( psSHP->fpSHX, 0, 0 ) != 0 
+        || fwrite( abyHeader, 100, 1, psSHP->fpSHX ) != 1 )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "Failure writing .shx header." );
+#endif
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write out the .shx contents.                                    */
+/* -------------------------------------------------------------------- */
+    panSHX = (int32 *) malloc(sizeof(int32) * 2 * psSHP->nRecords);
+
+    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 );
+    }
+
+    if( fwrite( panSHX, sizeof(int32) * 2, psSHP->nRecords, psSHP->fpSHX ) 
+        != psSHP->nRecords )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "Failure writing .shx contents." );
+#endif
+    }
+
+    free( panSHX );
+
+/* -------------------------------------------------------------------- */
+/*      Flush to disk.                                                  */
+/* -------------------------------------------------------------------- */
+    fflush( psSHP->fpSHP );
+    fflush( psSHP->fpSHX );
+}
+
+/************************************************************************/
+/*                              shpopen()                               */
+/*                                                                      */
+/*      Open the .shp and .shx files based on the basename of the       */
+/*      files or either file name.                                      */
+/************************************************************************/
+   
+SHPHandle SHPAPI_CALL
+SHPOpen( const char * pszLayer, const char * pszAccess )
+
+{
+    char		*pszFullname, *pszBasename;
+    SHPHandle		psSHP;
+    
+    uchar		*pabyBuf;
+    int			i;
+    double		dValue;
+    
+/* -------------------------------------------------------------------- */
+/*      Ensure the access string is one of the legal ones.  We          */
+/*      ensure the result string indicates binary to avoid common       */
+/*      problems on Windows.                                            */
+/* -------------------------------------------------------------------- */
+    if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
+        || strcmp(pszAccess,"r+") == 0 )
+        pszAccess = "r+b";
+    else
+        pszAccess = "rb";
+    
+/* -------------------------------------------------------------------- */
+/*	Establish the byte order on this machine.			*/
+/* -------------------------------------------------------------------- */
+    i = 1;
+    if( *((uchar *) &i) == 1 )
+        bBigEndian = FALSE;
+    else
+        bBigEndian = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*	Initialize the info structure.					*/
+/* -------------------------------------------------------------------- */
+    psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1);
+
+    psSHP->bUpdated = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*	Compute the base (layer) name.  If there is any extension	*/
+/*	on the passed in filename we will strip it off.			*/
+/* -------------------------------------------------------------------- */
+    pszBasename = (char *) malloc(strlen(pszLayer)+5);
+    strcpy( pszBasename, pszLayer );
+    for( i = strlen(pszBasename)-1; 
+	 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+	       && pszBasename[i] != '\\';
+	 i-- ) {}
+
+    if( pszBasename[i] == '.' )
+        pszBasename[i] = '\0';
+
+/* -------------------------------------------------------------------- */
+/*	Open the .shp and .shx files.  Note that files pulled from	*/
+/*	a PC to Unix with upper case filenames won't work!		*/
+/* -------------------------------------------------------------------- */
+    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+    sprintf( pszFullname, "%s.shp", pszBasename );
+    psSHP->fpSHP = fopen(pszFullname, pszAccess );
+    if( psSHP->fpSHP == NULL )
+    {
+        sprintf( pszFullname, "%s.SHP", pszBasename );
+        psSHP->fpSHP = fopen(pszFullname, pszAccess );
+    }
+    
+    if( psSHP->fpSHP == NULL )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "Unable to open %s.shp or %s.SHP.", 
+                  pszBasename, pszBasename );
+#endif
+        free( psSHP );
+        free( pszBasename );
+        free( pszFullname );
+        return( NULL );
+    }
+
+    sprintf( pszFullname, "%s.shx", pszBasename );
+    psSHP->fpSHX = fopen(pszFullname, pszAccess );
+    if( psSHP->fpSHX == NULL )
+    {
+        sprintf( pszFullname, "%s.SHX", pszBasename );
+        psSHP->fpSHX = fopen(pszFullname, pszAccess );
+    }
+    
+    if( psSHP->fpSHX == NULL )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "Unable to open %s.shx or %s.SHX.", 
+                  pszBasename, pszBasename );
+#endif
+        fclose( psSHP->fpSHP );
+        free( psSHP );
+        free( pszBasename );
+        free( pszFullname );
+        return( NULL );
+    }
+
+    free( pszFullname );
+    free( pszBasename );
+
+/* -------------------------------------------------------------------- */
+/*  Read the file size from the SHP file.				*/
+/* -------------------------------------------------------------------- */
+    pabyBuf = (uchar *) malloc(100);
+    fread( pabyBuf, 100, 1, psSHP->fpSHP );
+
+    psSHP->nFileSize = (pabyBuf[24] * 256 * 256 * 256
+			+ pabyBuf[25] * 256 * 256
+			+ pabyBuf[26] * 256
+			+ pabyBuf[27]) * 2;
+
+/* -------------------------------------------------------------------- */
+/*  Read SHX file Header info                                           */
+/* -------------------------------------------------------------------- */
+    if( fread( pabyBuf, 100, 1, psSHP->fpSHX ) != 1 
+        || pabyBuf[0] != 0 
+        || pabyBuf[1] != 0 
+        || pabyBuf[2] != 0x27 
+        || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  ".shx file is unreadable, or corrupt." );
+#endif
+	fclose( psSHP->fpSHP );
+	fclose( psSHP->fpSHX );
+	free( psSHP );
+
+	return( NULL );
+    }
+
+    psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
+      + pabyBuf[25] * 256 * 256 + pabyBuf[24] * 256 * 256 * 256;
+    psSHP->nRecords = (psSHP->nRecords*2 - 100) / 8;
+
+    psSHP->nShapeType = pabyBuf[32];
+
+    if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Record count in .shp header is %d, which seems\n"
+                  "unreasonable.  Assuming header is corrupt.",
+                  psSHP->nRecords );
+#endif
+	fclose( psSHP->fpSHP );
+	fclose( psSHP->fpSHX );
+	free( psSHP );
+
+	return( NULL );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read the bounds.                                                */
+/* -------------------------------------------------------------------- */
+    if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
+    memcpy( &dValue, pabyBuf+36, 8 );
+    psSHP->adBoundsMin[0] = dValue;
+
+    if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
+    memcpy( &dValue, pabyBuf+44, 8 );
+    psSHP->adBoundsMin[1] = dValue;
+
+    if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
+    memcpy( &dValue, pabyBuf+52, 8 );
+    psSHP->adBoundsMax[0] = dValue;
+
+    if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
+    memcpy( &dValue, pabyBuf+60, 8 );
+    psSHP->adBoundsMax[1] = dValue;
+
+    if( bBigEndian ) SwapWord( 8, pabyBuf+68 );		/* z */
+    memcpy( &dValue, pabyBuf+68, 8 );
+    psSHP->adBoundsMin[2] = dValue;
+    
+    if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
+    memcpy( &dValue, pabyBuf+76, 8 );
+    psSHP->adBoundsMax[2] = dValue;
+    
+    if( bBigEndian ) SwapWord( 8, pabyBuf+84 );		/* z */
+    memcpy( &dValue, pabyBuf+84, 8 );
+    psSHP->adBoundsMin[3] = dValue;
+
+    if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
+    memcpy( &dValue, pabyBuf+92, 8 );
+    psSHP->adBoundsMax[3] = dValue;
+
+    free( pabyBuf );
+
+/* -------------------------------------------------------------------- */
+/*	Read the .shx file to get the offsets to each record in 	*/
+/*	the .shp file.							*/
+/* -------------------------------------------------------------------- */
+    psSHP->nMaxRecords = psSHP->nRecords;
+
+    psSHP->panRecOffset =
+        (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
+    psSHP->panRecSize =
+        (int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
+
+    pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
+    if( fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ) != psSHP->nRecords )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Failed to read all values for %d records in .shx file.",
+                  psSHP->nRecords );
+#endif
+        /* SHX is short or unreadable for some reason. */
+	fclose( psSHP->fpSHP );
+	fclose( psSHP->fpSHX );
+        free( psSHP->panRecOffset );
+        free( psSHP->panRecSize );
+	free( psSHP );
+
+	return( NULL );
+    }
+
+    for( i = 0; i < psSHP->nRecords; i++ )
+    {
+	int32		nOffset, nLength;
+
+	memcpy( &nOffset, pabyBuf + i * 8, 4 );
+	if( !bBigEndian ) SwapWord( 4, &nOffset );
+
+	memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
+	if( !bBigEndian ) SwapWord( 4, &nLength );
+
+	psSHP->panRecOffset[i] = nOffset*2;
+	psSHP->panRecSize[i] = nLength*2;
+    }
+    free( pabyBuf );
+
+    return( psSHP );
+}
+
+/************************************************************************/
+/*                              SHPClose()                              */
+/*								       	*/
+/*	Close the .shp and .shx files.					*/
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPClose(SHPHandle psSHP )
+
+{
+    if( psSHP == NULL )
+        return;
+
+/* -------------------------------------------------------------------- */
+/*	Update the header if we have modified anything.			*/
+/* -------------------------------------------------------------------- */
+    if( psSHP->bUpdated )
+	SHPWriteHeader( psSHP );
+
+/* -------------------------------------------------------------------- */
+/*      Free all resources, and close files.                            */
+/* -------------------------------------------------------------------- */
+    free( psSHP->panRecOffset );
+    free( psSHP->panRecSize );
+
+    fclose( psSHP->fpSHX );
+    fclose( psSHP->fpSHP );
+
+    if( psSHP->pabyRec != NULL )
+    {
+        free( psSHP->pabyRec );
+    }
+    
+    free( psSHP );
+}
+
+/************************************************************************/
+/*                             SHPGetInfo()                             */
+/*                                                                      */
+/*      Fetch general information about the shape file.                 */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
+           double * padfMinBound, double * padfMaxBound )
+
+{
+    int		i;
+
+    if( psSHP == NULL )
+        return;
+    
+    if( pnEntities != NULL )
+        *pnEntities = psSHP->nRecords;
+
+    if( pnShapeType != NULL )
+        *pnShapeType = psSHP->nShapeType;
+
+    for( i = 0; i < 4; i++ )
+    {
+        if( padfMinBound != NULL )
+            padfMinBound[i] = psSHP->adBoundsMin[i];
+        if( padfMaxBound != NULL )
+            padfMaxBound[i] = psSHP->adBoundsMax[i];
+    }
+}
+
+/************************************************************************/
+/*                             SHPCreate()                              */
+/*                                                                      */
+/*      Create a new shape file and return a handle to the open         */
+/*      shape file with read/write access.                              */
+/************************************************************************/
+
+SHPHandle SHPAPI_CALL
+SHPCreate( const char * pszLayer, int nShapeType )
+
+{
+    char	*pszBasename, *pszFullname;
+    int		i;
+    FILE	*fpSHP, *fpSHX;
+    uchar     	abyHeader[100];
+    int32	i32;
+    double	dValue;
+    
+/* -------------------------------------------------------------------- */
+/*      Establish the byte order on this system.                        */
+/* -------------------------------------------------------------------- */
+    i = 1;
+    if( *((uchar *) &i) == 1 )
+        bBigEndian = FALSE;
+    else
+        bBigEndian = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*	Compute the base (layer) name.  If there is any extension	*/
+/*	on the passed in filename we will strip it off.			*/
+/* -------------------------------------------------------------------- */
+    pszBasename = (char *) malloc(strlen(pszLayer)+5);
+    strcpy( pszBasename, pszLayer );
+    for( i = strlen(pszBasename)-1; 
+	 i > 0 && pszBasename[i] != '.' && pszBasename[i] != '/'
+	       && pszBasename[i] != '\\';
+	 i-- ) {}
+
+    if( pszBasename[i] == '.' )
+        pszBasename[i] = '\0';
+
+/* -------------------------------------------------------------------- */
+/*      Open the two files so we can write their headers.               */
+/* -------------------------------------------------------------------- */
+    pszFullname = (char *) malloc(strlen(pszBasename) + 5);
+    sprintf( pszFullname, "%s.shp", pszBasename );
+    fpSHP = fopen(pszFullname, "wb" );
+    if( fpSHP == NULL )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Failed to create file %s.",
+                  pszFullname );
+#endif
+        return( NULL );
+    }
+
+    sprintf( pszFullname, "%s.shx", pszBasename );
+    fpSHX = fopen(pszFullname, "wb" );
+    if( fpSHX == NULL )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Failed to create file %s.",
+                  pszFullname );
+#endif
+        return( NULL );
+    }
+
+    free( pszFullname );
+    free( pszBasename );
+
+/* -------------------------------------------------------------------- */
+/*      Prepare header block for .shp file.                             */
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < 100; i++ )
+      abyHeader[i] = 0;
+
+    abyHeader[2] = 0x27;				/* magic cookie */
+    abyHeader[3] = 0x0a;
+
+    i32 = 50;						/* file size */
+    ByteCopy( &i32, abyHeader+24, 4 );
+    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+    
+    i32 = 1000;						/* version */
+    ByteCopy( &i32, abyHeader+28, 4 );
+    if( bBigEndian ) SwapWord( 4, abyHeader+28 );
+    
+    i32 = nShapeType;					/* shape type */
+    ByteCopy( &i32, abyHeader+32, 4 );
+    if( bBigEndian ) SwapWord( 4, abyHeader+32 );
+
+    dValue = 0.0;					/* set bounds */
+    ByteCopy( &dValue, abyHeader+36, 8 );
+    ByteCopy( &dValue, abyHeader+44, 8 );
+    ByteCopy( &dValue, abyHeader+52, 8 );
+    ByteCopy( &dValue, abyHeader+60, 8 );
+
+/* -------------------------------------------------------------------- */
+/*      Write .shp file header.                                         */
+/* -------------------------------------------------------------------- */
+    if( fwrite( abyHeader, 100, 1, fpSHP ) != 1 )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Failed to write .shp header." );
+#endif
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Prepare, and write .shx file header.                            */
+/* -------------------------------------------------------------------- */
+    i32 = 50;						/* file size */
+    ByteCopy( &i32, abyHeader+24, 4 );
+    if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+    
+    if( fwrite( abyHeader, 100, 1, fpSHX ) != 1 )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Failed to write .shx header." );
+#endif
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Close the files, and then open them as regular existing files.  */
+/* -------------------------------------------------------------------- */
+    fclose( fpSHP );
+    fclose( fpSHX );
+
+    return( SHPOpen( pszLayer, "r+b" ) );
+}
+
+/************************************************************************/
+/*                           _SHPSetBounds()                            */
+/*                                                                      */
+/*      Compute a bounds rectangle for a shape, and set it into the     */
+/*      indicated location in the record.                               */
+/************************************************************************/
+
+static void	_SHPSetBounds( uchar * pabyRec, SHPObject * psShape )
+
+{
+    ByteCopy( &(psShape->dfXMin), pabyRec +  0, 8 );
+    ByteCopy( &(psShape->dfYMin), pabyRec +  8, 8 );
+    ByteCopy( &(psShape->dfXMax), pabyRec + 16, 8 );
+    ByteCopy( &(psShape->dfYMax), pabyRec + 24, 8 );
+
+    if( bBigEndian )
+    {
+        SwapWord( 8, pabyRec + 0 );
+        SwapWord( 8, pabyRec + 8 );
+        SwapWord( 8, pabyRec + 16 );
+        SwapWord( 8, pabyRec + 24 );
+    }
+}
+
+/************************************************************************/
+/*                         SHPComputeExtents()                          */
+/*                                                                      */
+/*      Recompute the extents of a shape.  Automatically done by        */
+/*      SHPCreateObject().                                              */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPComputeExtents( SHPObject * psObject )
+
+{
+    int		i;
+    
+/* -------------------------------------------------------------------- */
+/*      Build extents for this object.                                  */
+/* -------------------------------------------------------------------- */
+    if( psObject->nVertices > 0 )
+    {
+        psObject->dfXMin = psObject->dfXMax = psObject->padfX[0];
+        psObject->dfYMin = psObject->dfYMax = psObject->padfY[0];
+        psObject->dfZMin = psObject->dfZMax = psObject->padfZ[0];
+        psObject->dfMMin = psObject->dfMMax = psObject->padfM[0];
+    }
+    
+    for( i = 0; i < psObject->nVertices; i++ )
+    {
+        psObject->dfXMin = MIN(psObject->dfXMin, psObject->padfX[i]);
+        psObject->dfYMin = MIN(psObject->dfYMin, psObject->padfY[i]);
+        psObject->dfZMin = MIN(psObject->dfZMin, psObject->padfZ[i]);
+        psObject->dfMMin = MIN(psObject->dfMMin, psObject->padfM[i]);
+
+        psObject->dfXMax = MAX(psObject->dfXMax, psObject->padfX[i]);
+        psObject->dfYMax = MAX(psObject->dfYMax, psObject->padfY[i]);
+        psObject->dfZMax = MAX(psObject->dfZMax, psObject->padfZ[i]);
+        psObject->dfMMax = MAX(psObject->dfMMax, psObject->padfM[i]);
+    }
+}
+
+/************************************************************************/
+/*                          SHPCreateObject()                           */
+/*                                                                      */
+/*      Create a shape object.  It should be freed with                 */
+/*      SHPDestroyObject().                                             */
+/************************************************************************/
+
+SHPObject SHPAPI_CALL1(*)
+SHPCreateObject( int nSHPType, int nShapeId, int nParts,
+                 int * panPartStart, int * panPartType,
+                 int nVertices, double * padfX, double * padfY,
+                 double * padfZ, double * padfM )
+
+{
+    SHPObject	*psObject;
+    int		i, bHasM, bHasZ;
+
+    psObject = (SHPObject *) calloc(1,sizeof(SHPObject));
+    psObject->nSHPType = nSHPType;
+    psObject->nShapeId = nShapeId;
+
+/* -------------------------------------------------------------------- */
+/*	Establish whether this shape type has M, and Z values.		*/
+/* -------------------------------------------------------------------- */
+    if( nSHPType == SHPT_ARCM
+        || nSHPType == SHPT_POINTM
+        || nSHPType == SHPT_POLYGONM
+        || nSHPType == SHPT_MULTIPOINTM )
+    {
+        bHasM = TRUE;
+        bHasZ = FALSE;
+    }
+    else if( nSHPType == SHPT_ARCZ
+             || nSHPType == SHPT_POINTZ
+             || nSHPType == SHPT_POLYGONZ
+             || nSHPType == SHPT_MULTIPOINTZ
+             || nSHPType == SHPT_MULTIPATCH )
+    {
+        bHasM = TRUE;
+        bHasZ = TRUE;
+    }
+    else
+    {
+        bHasM = FALSE;
+        bHasZ = FALSE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Capture parts.  Note that part type is optional, and            */
+/*      defaults to ring.                                               */
+/* -------------------------------------------------------------------- */
+    if( nSHPType == SHPT_ARC || nSHPType == SHPT_POLYGON
+        || nSHPType == SHPT_ARCM || nSHPType == SHPT_POLYGONM
+        || nSHPType == SHPT_ARCZ || nSHPType == SHPT_POLYGONZ
+        || nSHPType == SHPT_MULTIPATCH )
+    {
+        psObject->nParts = MAX(1,nParts);
+
+        psObject->panPartStart = (int *)
+            malloc(sizeof(int) * psObject->nParts);
+        psObject->panPartType = (int *)
+            malloc(sizeof(int) * psObject->nParts);
+
+        psObject->panPartStart[0] = 0;
+        psObject->panPartType[0] = SHPP_RING;
+        
+        for( i = 0; i < nParts; i++ )
+        {
+            psObject->panPartStart[i] = panPartStart[i];
+            if( panPartType != NULL )
+                psObject->panPartType[i] = panPartType[i];
+            else
+                psObject->panPartType[i] = SHPP_RING;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Capture vertices.  Note that Z and M are optional, but X and    */
+/*      Y are not.                                                      */
+/* -------------------------------------------------------------------- */
+    if( nVertices > 0 )
+    {
+        psObject->padfX = (double *) calloc(sizeof(double),nVertices);
+        psObject->padfY = (double *) calloc(sizeof(double),nVertices);
+        psObject->padfZ = (double *) calloc(sizeof(double),nVertices);
+        psObject->padfM = (double *) calloc(sizeof(double),nVertices);
+
+        assert( padfX != NULL );
+        assert( padfY != NULL );
+    
+        for( i = 0; i < nVertices; i++ )
+        {
+            psObject->padfX[i] = padfX[i];
+            psObject->padfY[i] = padfY[i];
+            if( padfZ != NULL && bHasZ )
+                psObject->padfZ[i] = padfZ[i];
+            if( padfM != NULL && bHasM )
+                psObject->padfM[i] = padfM[i];
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Compute the extents.                                            */
+/* -------------------------------------------------------------------- */
+    psObject->nVertices = nVertices;
+    SHPComputeExtents( psObject );
+
+    return( psObject );
+}
+
+/************************************************************************/
+/*                       SHPCreateSimpleObject()                        */
+/*                                                                      */
+/*      Create a simple (common) shape object.  Destroy with            */
+/*      SHPDestroyObject().                                             */
+/************************************************************************/
+
+SHPObject SHPAPI_CALL1(*)
+SHPCreateSimpleObject( int nSHPType, int nVertices,
+                       double * padfX, double * padfY,
+                       double * padfZ )
+
+{
+    return( SHPCreateObject( nSHPType, -1, 0, NULL, NULL,
+                             nVertices, padfX, padfY, padfZ, NULL ) );
+}
+                                  
+/************************************************************************/
+/*                           SHPWriteObject()                           */
+/*                                                                      */
+/*      Write out the vertices of a new structure.  Note that it is     */
+/*      only possible to write vertices at the end of the file.         */
+/************************************************************************/
+
+int SHPAPI_CALL
+SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
+		      
+{
+    int	       	nRecordOffset, i, nRecordSize=0;
+    uchar	*pabyRec;
+    int32	i32;
+
+    psSHP->bUpdated = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Ensure that shape object matches the type of the file it is     */
+/*      being written to.                                               */
+/* -------------------------------------------------------------------- */
+    assert( psObject->nSHPType == psSHP->nShapeType 
+            || psObject->nSHPType == SHPT_NULL );
+
+/* -------------------------------------------------------------------- */
+/*      Ensure that -1 is used for appends.  Either blow an             */
+/*      assertion, or if they are disabled, set the shapeid to -1       */
+/*      for appends.                                                    */
+/* -------------------------------------------------------------------- */
+    assert( nShapeId == -1 
+            || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
+
+    if( nShapeId != -1 && nShapeId >= psSHP->nRecords )
+        nShapeId = -1;
+
+/* -------------------------------------------------------------------- */
+/*      Add the new entity to the in memory index.                      */
+/* -------------------------------------------------------------------- */
+    if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
+    {
+	psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
+
+	psSHP->panRecOffset = (int *) 
+            SfRealloc(psSHP->panRecOffset,sizeof(int) * psSHP->nMaxRecords );
+	psSHP->panRecSize = (int *) 
+            SfRealloc(psSHP->panRecSize,sizeof(int) * psSHP->nMaxRecords );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize record.                                              */
+/* -------------------------------------------------------------------- */
+    pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double) 
+			       + psObject->nParts * 8 + 128);
+    
+/* -------------------------------------------------------------------- */
+/*  Extract vertices for a Polygon or Arc.				*/
+/* -------------------------------------------------------------------- */
+    if( psObject->nSHPType == SHPT_POLYGON
+        || psObject->nSHPType == SHPT_POLYGONZ
+        || psObject->nSHPType == SHPT_POLYGONM
+        || psObject->nSHPType == SHPT_ARC 
+        || psObject->nSHPType == SHPT_ARCZ
+        || psObject->nSHPType == SHPT_ARCM
+        || psObject->nSHPType == SHPT_MULTIPATCH )
+    {
+	int32		nPoints, nParts;
+	int    		i;
+
+	nPoints = psObject->nVertices;
+	nParts = psObject->nParts;
+
+	_SHPSetBounds( pabyRec + 12, psObject );
+
+	if( bBigEndian ) SwapWord( 4, &nPoints );
+	if( bBigEndian ) SwapWord( 4, &nParts );
+
+	ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
+	ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
+
+        nRecordSize = 52;
+
+        /*
+         * Write part start positions.
+         */
+	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 );
+            nRecordSize += 4;
+	}
+
+        /*
+         * Write multipatch part types if needed.
+         */
+        if( psObject->nSHPType == SHPT_MULTIPATCH )
+        {
+            memcpy( pabyRec + nRecordSize, psObject->panPartType,
+                    4*psObject->nParts );
+            for( i = 0; i < psObject->nParts; i++ )
+            {
+                if( bBigEndian ) SwapWord( 4, pabyRec + nRecordSize );
+                nRecordSize += 4;
+            }
+        }
+
+        /*
+         * 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 );
+
+	    if( bBigEndian )
+                SwapWord( 8, pabyRec + nRecordSize );
+            
+	    if( bBigEndian )
+                SwapWord( 8, pabyRec + nRecordSize + 8 );
+
+            nRecordSize += 2 * 8;
+	}
+
+        /*
+         * Write the Z coordinates (if any).
+         */
+        if( psObject->nSHPType == SHPT_POLYGONZ
+            || psObject->nSHPType == SHPT_ARCZ
+            || psObject->nSHPType == SHPT_MULTIPATCH )
+        {
+            ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            nRecordSize += 8;
+            
+            ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            nRecordSize += 8;
+
+            for( i = 0; i < psObject->nVertices; i++ )
+            {
+                ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
+                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+                nRecordSize += 8;
+            }
+        }
+
+        /*
+         * Write the M values, if any.
+         */
+        if( psObject->nSHPType == SHPT_POLYGONM
+            || psObject->nSHPType == SHPT_ARCM
+#ifndef DISABLE_MULTIPATCH_MEASURE            
+            || psObject->nSHPType == SHPT_MULTIPATCH
+#endif            
+            || psObject->nSHPType == SHPT_POLYGONZ
+            || psObject->nSHPType == SHPT_ARCZ )
+        {
+            ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            nRecordSize += 8;
+            
+            ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            nRecordSize += 8;
+
+            for( i = 0; i < psObject->nVertices; i++ )
+            {
+                ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
+                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+                nRecordSize += 8;
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*  Extract vertices for a MultiPoint.					*/
+/* -------------------------------------------------------------------- */
+    else if( psObject->nSHPType == SHPT_MULTIPOINT
+             || psObject->nSHPType == SHPT_MULTIPOINTZ
+             || psObject->nSHPType == SHPT_MULTIPOINTM )
+    {
+	int32		nPoints;
+	int    		i;
+
+	nPoints = psObject->nVertices;
+
+        _SHPSetBounds( pabyRec + 12, psObject );
+
+	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 );
+
+	    if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
+	    if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
+	}
+
+	nRecordSize = 48 + 16 * psObject->nVertices;
+
+        if( psObject->nSHPType == SHPT_MULTIPOINTZ )
+        {
+            ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            nRecordSize += 8;
+
+            ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            nRecordSize += 8;
+            
+            for( i = 0; i < psObject->nVertices; i++ )
+            {
+                ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
+                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+                nRecordSize += 8;
+            }
+        }
+
+        if( psObject->nSHPType == SHPT_MULTIPOINTZ
+            || psObject->nSHPType == SHPT_MULTIPOINTM )
+        {
+            ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            nRecordSize += 8;
+
+            ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            nRecordSize += 8;
+            
+            for( i = 0; i < psObject->nVertices; i++ )
+            {
+                ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
+                if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+                nRecordSize += 8;
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write point.							*/
+/* -------------------------------------------------------------------- */
+    else if( psObject->nSHPType == SHPT_POINT
+             || psObject->nSHPType == SHPT_POINTZ
+             || psObject->nSHPType == SHPT_POINTM )
+    {
+	ByteCopy( psObject->padfX, pabyRec + 12, 8 );
+	ByteCopy( psObject->padfY, pabyRec + 20, 8 );
+
+	if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
+	if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
+
+        nRecordSize = 28;
+        
+        if( psObject->nSHPType == SHPT_POINTZ )
+        {
+            ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            nRecordSize += 8;
+        }
+        
+        if( psObject->nSHPType == SHPT_POINTZ
+            || psObject->nSHPType == SHPT_POINTM )
+        {
+            ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
+            if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+            nRecordSize += 8;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Not much to do for null geometries.                             */
+/* -------------------------------------------------------------------- */
+    else if( psObject->nSHPType == SHPT_NULL )
+    {
+        nRecordSize = 12;
+    }
+
+    else
+    {
+        /* unknown type */
+        assert( FALSE );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Establish where we are going to put this record. If we are      */
+/*      rewriting and existing record, and it will fit, then put it     */
+/*      back where the original came from.  Otherwise write at the end. */
+/* -------------------------------------------------------------------- */
+    if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
+    {
+        if( nShapeId == -1 )
+            nShapeId = psSHP->nRecords++;
+
+        psSHP->panRecOffset[nShapeId] = nRecordOffset = psSHP->nFileSize;
+        psSHP->panRecSize[nShapeId] = nRecordSize-8;
+        psSHP->nFileSize += nRecordSize;
+    }
+    else
+    {
+        nRecordOffset = psSHP->panRecOffset[nShapeId];
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      Set the shape type, record number, and record size.             */
+/* -------------------------------------------------------------------- */
+    i32 = nShapeId+1;					/* record # */
+    if( !bBigEndian ) SwapWord( 4, &i32 );
+    ByteCopy( &i32, pabyRec, 4 );
+
+    i32 = (nRecordSize-8)/2;				/* record size */
+    if( !bBigEndian ) SwapWord( 4, &i32 );
+    ByteCopy( &i32, pabyRec + 4, 4 );
+
+    i32 = psObject->nSHPType;				/* shape type */
+    if( bBigEndian ) SwapWord( 4, &i32 );
+    ByteCopy( &i32, pabyRec + 8, 4 );
+
+/* -------------------------------------------------------------------- */
+/*      Write out record.                                               */
+/* -------------------------------------------------------------------- */
+    if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0
+        || fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_FileIO, 
+                "Error in fseek() or fwrite() writing object to .shp file." );
+#endif
+        free( pabyRec );
+        return -1;
+    }
+    
+    free( pabyRec );
+
+/* -------------------------------------------------------------------- */
+/*	Expand file wide bounds based on this shape.			*/
+/* -------------------------------------------------------------------- */
+    if( psSHP->adBoundsMin[0] == 0.0
+        && psSHP->adBoundsMax[0] == 0.0
+        && psSHP->adBoundsMin[1] == 0.0
+        && psSHP->adBoundsMax[1] == 0.0 )
+    {
+        if( psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0 )
+        {
+            psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = 0.0;
+            psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = 0.0;
+            psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = 0.0;
+            psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = 0.0;
+        }
+        else
+        {
+            psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
+            psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
+            psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
+            psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
+        }
+    }
+
+    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]);
+    }
+
+    return( nShapeId  );
+}
+
+/************************************************************************/
+/*                          SHPReadObject()                             */
+/*                                                                      */
+/*      Read the vertices, parts, and other non-attribute information	*/
+/*	for one shape.							*/
+/************************************************************************/
+
+SHPObject SHPAPI_CALL1(*)
+SHPReadObject( SHPHandle psSHP, int hEntity )
+
+{
+    SHPObject		*psShape;
+
+/* -------------------------------------------------------------------- */
+/*      Validate the record/entity number.                              */
+/* -------------------------------------------------------------------- */
+    if( hEntity < 0 || hEntity >= psSHP->nRecords )
+        return( NULL );
+
+/* -------------------------------------------------------------------- */
+/*      Ensure our record buffer is large enough.                       */
+/* -------------------------------------------------------------------- */
+    if( psSHP->panRecSize[hEntity]+8 > psSHP->nBufSize )
+    {
+	psSHP->nBufSize = psSHP->panRecSize[hEntity]+8;
+	psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,psSHP->nBufSize);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Read the record.                                                */
+/* -------------------------------------------------------------------- */
+    if( fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 
+        || fread( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1, 
+                  psSHP->fpSHP ) != 1 )
+    {
+#ifdef USE_CPL
+        CPLError( CE_Failure, CPLE_FileIO, 
+                "Error in fseek() or fread() reading object from .shp file." );
+#endif
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*	Allocate and minimally initialize the object.			*/
+/* -------------------------------------------------------------------- */
+    psShape = (SHPObject *) calloc(1,sizeof(SHPObject));
+    psShape->nShapeId = hEntity;
+
+    memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 );
+    if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
+
+/* ==================================================================== */
+/*  Extract vertices for a Polygon or Arc.				*/
+/* ==================================================================== */
+    if( psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC
+        || psShape->nSHPType == SHPT_POLYGONZ
+        || psShape->nSHPType == SHPT_POLYGONM
+        || psShape->nSHPType == SHPT_ARCZ
+        || psShape->nSHPType == SHPT_ARCM
+        || psShape->nSHPType == SHPT_MULTIPATCH )
+    {
+	int32		nPoints, nParts;
+	int    		i, nOffset;
+
+/* -------------------------------------------------------------------- */
+/*	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) );
+
+/* -------------------------------------------------------------------- */
+/*      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 );
+
+	if( bBigEndian ) SwapWord( 4, &nPoints );
+	if( bBigEndian ) SwapWord( 4, &nParts );
+
+	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->panPartStart = (int *) calloc(nParts,sizeof(int));
+        psShape->panPartType = (int *) calloc(nParts,sizeof(int));
+
+        for( i = 0; i < nParts; i++ )
+            psShape->panPartType[i] = SHPP_RING;
+
+/* -------------------------------------------------------------------- */
+/*      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 );
+	}
+
+	nOffset = 44 + 8 + 4*nParts;
+
+/* -------------------------------------------------------------------- */
+/*      If this is a multipatch, we will also have parts types.         */
+/* -------------------------------------------------------------------- */
+        if( psShape->nSHPType == SHPT_MULTIPATCH )
+        {
+            memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
+            for( i = 0; i < nParts; i++ )
+            {
+                if( bBigEndian ) SwapWord( 4, psShape->panPartType+i );
+            }
+
+            nOffset += 4*nParts;
+        }
+        
+/* -------------------------------------------------------------------- */
+/*      Copy out the vertices from the record.                          */
+/* -------------------------------------------------------------------- */
+	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 );
+
+	    if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
+	    if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+	}
+
+        nOffset += 16*nPoints;
+        
+/* -------------------------------------------------------------------- */
+/*      If we have a Z coordinate, collect that now.                    */
+/* -------------------------------------------------------------------- */
+        if( psShape->nSHPType == SHPT_POLYGONZ
+            || psShape->nSHPType == SHPT_ARCZ
+            || psShape->nSHPType == SHPT_MULTIPATCH )
+        {
+            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 );
+            }
+        }
+        
+    }
+
+/* ==================================================================== */
+/*  Extract vertices for a MultiPoint.					*/
+/* ==================================================================== */
+    else if( psShape->nSHPType == SHPT_MULTIPOINT
+             || psShape->nSHPType == SHPT_MULTIPOINTM
+             || psShape->nSHPType == SHPT_MULTIPOINTZ )
+    {
+	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 )
+        {
+            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 );
+            }
+        }
+    }
+
+/* ==================================================================== */
+/*      Extract vertices for a point.                                   */
+/* ==================================================================== */
+    else if( psShape->nSHPType == SHPT_POINT
+             || psShape->nSHPType == SHPT_POINTM
+             || psShape->nSHPType == SHPT_POINTZ )
+    {
+        int	nOffset;
+        
+	psShape->nVertices = 1;
+        psShape->padfX = (double *) calloc(1,sizeof(double));
+        psShape->padfY = (double *) calloc(1,sizeof(double));
+        psShape->padfZ = (double *) calloc(1,sizeof(double));
+        psShape->padfM = (double *) calloc(1,sizeof(double));
+
+	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 );
+
+        nOffset = 20 + 8;
+        
+/* -------------------------------------------------------------------- */
+/*      If we have a Z coordinate, collect that now.                    */
+/* -------------------------------------------------------------------- */
+        if( psShape->nSHPType == SHPT_POINTZ )
+        {
+            memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
+        
+            if( bBigEndian ) SwapWord( 8, psShape->padfZ );
+            
+            nOffset += 8;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      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 + 8 )
+        {
+            memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
+        
+            if( bBigEndian ) SwapWord( 8, psShape->padfM );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Since no extents are supplied in the record, we will apply      */
+/*      them from the single vertex.                                    */
+/* -------------------------------------------------------------------- */
+        psShape->dfXMin = psShape->dfXMax = psShape->padfX[0];
+        psShape->dfYMin = psShape->dfYMax = psShape->padfY[0];
+        psShape->dfZMin = psShape->dfZMax = psShape->padfZ[0];
+        psShape->dfMMin = psShape->dfMMax = psShape->padfM[0];
+    }
+
+    return( psShape );
+}
+
+/************************************************************************/
+/*                            SHPTypeName()                             */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+SHPTypeName( int nSHPType )
+
+{
+    switch( nSHPType )
+    {
+      case SHPT_NULL:
+        return "NullShape";
+
+      case SHPT_POINT:
+        return "Point";
+
+      case SHPT_ARC:
+        return "Arc";
+
+      case SHPT_POLYGON:
+        return "Polygon";
+
+      case SHPT_MULTIPOINT:
+        return "MultiPoint";
+        
+      case SHPT_POINTZ:
+        return "PointZ";
+
+      case SHPT_ARCZ:
+        return "ArcZ";
+
+      case SHPT_POLYGONZ:
+        return "PolygonZ";
+
+      case SHPT_MULTIPOINTZ:
+        return "MultiPointZ";
+        
+      case SHPT_POINTM:
+        return "PointM";
+
+      case SHPT_ARCM:
+        return "ArcM";
+
+      case SHPT_POLYGONM:
+        return "PolygonM";
+
+      case SHPT_MULTIPOINTM:
+        return "MultiPointM";
+
+      case SHPT_MULTIPATCH:
+        return "MultiPatch";
+
+      default:
+        return "UnknownShapeType";
+    }
+}
+
+/************************************************************************/
+/*                          SHPPartTypeName()                           */
+/************************************************************************/
+
+const char SHPAPI_CALL1(*)
+SHPPartTypeName( int nPartType )
+
+{
+    switch( nPartType )
+    {
+      case SHPP_TRISTRIP:
+        return "TriangleStrip";
+        
+      case SHPP_TRIFAN:
+        return "TriangleFan";
+
+      case SHPP_OUTERRING:
+        return "OuterRing";
+
+      case SHPP_INNERRING:
+        return "InnerRing";
+
+      case SHPP_FIRSTRING:
+        return "FirstRing";
+
+      case SHPP_RING:
+        return "Ring";
+
+      default:
+        return "UnknownPartType";
+    }
+}
+
+/************************************************************************/
+/*                          SHPDestroyObject()                          */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPDestroyObject( SHPObject * psShape )
+
+{
+    if( psShape == NULL )
+        return;
+    
+    if( psShape->padfX != NULL )
+        free( psShape->padfX );
+    if( psShape->padfY != NULL )
+        free( psShape->padfY );
+    if( psShape->padfZ != NULL )
+        free( psShape->padfZ );
+    if( psShape->padfM != NULL )
+        free( psShape->padfM );
+
+    if( psShape->panPartStart != NULL )
+        free( psShape->panPartStart );
+    if( psShape->panPartType != NULL )
+        free( psShape->panPartType );
+
+    free( psShape );
+}
+
+/************************************************************************/
+/*                          SHPRewindObject()                           */
+/*                                                                      */
+/*      Reset the winding of polygon objects to adhere to the           */
+/*      specification.                                                  */
+/************************************************************************/
+
+int SHPAPI_CALL
+SHPRewindObject( SHPHandle hSHP, SHPObject * psObject )
+
+{
+    int  iOpRing, bAltered = 0;
+
+/* -------------------------------------------------------------------- */
+/*      Do nothing if this is not a polygon object.                     */
+/* -------------------------------------------------------------------- */
+    if( psObject->nSHPType != SHPT_POLYGON
+        && psObject->nSHPType != SHPT_POLYGONZ
+        && psObject->nSHPType != SHPT_POLYGONM )
+        return 0;
+
+    if( psObject->nVertices == 0 || psObject->nParts == 0 )
+        return 0;
+
+/* -------------------------------------------------------------------- */
+/*      Process each of the rings.                                      */
+/* -------------------------------------------------------------------- */
+    for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ )
+    {
+        int      bInner, iVert, nVertCount, nVertStart, iCheckRing;
+        double   dfSum, dfTestX, dfTestY;
+
+/* -------------------------------------------------------------------- */
+/*      Determine if this ring is an inner ring or an outer ring        */
+/*      relative to all the other rings.  For now we assume the         */
+/*      first ring is outer and all others are inner, but eventually    */
+/*      we need to fix this to handle multiple island polygons and      */
+/*      unordered sets of rings.                                        */
+/* -------------------------------------------------------------------- */
+        dfTestX = psObject->padfX[psObject->panPartStart[iOpRing]];
+        dfTestY = psObject->padfY[psObject->panPartStart[iOpRing]];
+
+        bInner = FALSE;
+        for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
+        {
+            int iEdge;
+
+            if( iCheckRing == iOpRing )
+                continue;
+            
+            nVertStart = psObject->panPartStart[iCheckRing];
+
+            if( iCheckRing == psObject->nParts-1 )
+                nVertCount = psObject->nVertices 
+                    - psObject->panPartStart[iCheckRing];
+            else
+                nVertCount = psObject->panPartStart[iCheckRing+1] 
+                    - psObject->panPartStart[iCheckRing];
+
+            for( iEdge = 0; iEdge < nVertCount; iEdge++ )
+            {
+                int iNext;
+
+                if( iEdge < nVertCount-1 )
+                    iNext = iEdge+1;
+                else
+                    iNext = 0;
+
+                if( (psObject->padfY[iEdge+nVertStart] < dfTestY 
+                     && psObject->padfY[iNext+nVertStart] >= dfTestY)
+                    || (psObject->padfY[iNext+nVertStart] < dfTestY 
+                        && psObject->padfY[iEdge+nVertStart] >= dfTestY) )
+                {
+                    if( psObject->padfX[iEdge+nVertStart] 
+                        + (dfTestY - psObject->padfY[iEdge+nVertStart])
+                           / (psObject->padfY[iNext+nVertStart]
+                              - psObject->padfY[iEdge+nVertStart])
+                           * (psObject->padfX[iNext+nVertStart]
+                              - psObject->padfX[iEdge+nVertStart]) < dfTestX )
+                        bInner = !bInner;
+                }
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Determine the current order of this ring so we will know if     */
+/*      it has to be reversed.                                          */
+/* -------------------------------------------------------------------- */
+        nVertStart = psObject->panPartStart[iOpRing];
+
+        if( iOpRing == psObject->nParts-1 )
+            nVertCount = psObject->nVertices - psObject->panPartStart[iOpRing];
+        else
+            nVertCount = psObject->panPartStart[iOpRing+1] 
+                - psObject->panPartStart[iOpRing];
+
+        dfSum = 0.0;
+        for( iVert = nVertStart; iVert < nVertStart+nVertCount-1; iVert++ )
+        {
+            dfSum += psObject->padfX[iVert] * psObject->padfY[iVert+1]
+                - psObject->padfY[iVert] * psObject->padfX[iVert+1];
+        }
+
+        dfSum += psObject->padfX[iVert] * psObject->padfY[nVertStart]
+               - psObject->padfY[iVert] * psObject->padfX[nVertStart];
+
+/* -------------------------------------------------------------------- */
+/*      Reverse if necessary.                                           */
+/* -------------------------------------------------------------------- */
+        if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
+        {
+            int   i;
+
+            bAltered++;
+            for( i = 0; i < nVertCount/2; i++ )
+            {
+                double dfSaved;
+
+                /* Swap X */
+                dfSaved = psObject->padfX[nVertStart+i];
+                psObject->padfX[nVertStart+i] = 
+                    psObject->padfX[nVertStart+nVertCount-i-1];
+                psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved;
+
+                /* Swap Y */
+                dfSaved = psObject->padfY[nVertStart+i];
+                psObject->padfY[nVertStart+i] = 
+                    psObject->padfY[nVertStart+nVertCount-i-1];
+                psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved;
+
+                /* Swap Z */
+                if( psObject->padfZ )
+                {
+                    dfSaved = psObject->padfZ[nVertStart+i];
+                    psObject->padfZ[nVertStart+i] = 
+                        psObject->padfZ[nVertStart+nVertCount-i-1];
+                    psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved;
+                }
+
+                /* Swap M */
+                if( psObject->padfM )
+                {
+                    dfSaved = psObject->padfM[nVertStart+i];
+                    psObject->padfM[nVertStart+i] = 
+                        psObject->padfM[nVertStart+nVertCount-i-1];
+                    psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved;
+                }
+            }
+        }
+    }
+
+    return bAltered;
+}

Added: packages/thuban/branches/upstream/current/libraries/shapelib/shptree.c
===================================================================
--- packages/thuban/branches/upstream/current/libraries/shapelib/shptree.c	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/shapelib/shptree.c	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,682 @@
+/******************************************************************************
+ * $Id: shptree.c 1769 2003-10-02 15:15:16Z bh $
+ *
+ * Project:  Shapelib
+ * Purpose:  Implementation of quadtree building and searching functions.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * This software is available under the following "MIT Style" license,
+ * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * option is discussed in more detail in shapelib.html.
+ *
+ * --
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log$
+ * Revision 1.2  2003/10/02 15:15:16  bh
+ * Update to shapelib 1.2.10
+ *
+ * Revision 1.9  2003/01/28 15:53:41  warmerda
+ * Avoid build warnings.
+ *
+ * Revision 1.8  2002/05/07 13:07:45  warmerda
+ * use qsort() - patch from Bernhard Herzog
+ *
+ * Revision 1.7  2002/01/15 14:36:07  warmerda
+ * updated email address
+ *
+ * Revision 1.6  2001/05/23 13:36:52  warmerda
+ * added use of SHPAPI_CALL
+ *
+ * Revision 1.5  1999/11/05 14:12:05  warmerda
+ * updated license terms
+ *
+ * Revision 1.4  1999/06/02 18:24:21  warmerda
+ * added trimming code
+ *
+ * Revision 1.3  1999/06/02 17:56:12  warmerda
+ * added quad'' subnode support for trees
+ *
+ * Revision 1.2  1999/05/18 19:11:11  warmerda
+ * Added example searching capability
+ *
+ * Revision 1.1  1999/05/18 17:49:20  warmerda
+ * New
+ *
+ */
+
+static char rcsid[] = 
+  "$Id: shptree.c 1769 2003-10-02 15:15:16Z bh $";
+
+#include "shapefil.h"
+
+#include <math.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef TRUE
+#  define TRUE 1
+#  define FALSE 0
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/*      If the following is 0.5, nodes will be split in half.  If it    */
+/*      is 0.6 then each subnode will contain 60% of the parent         */
+/*      node, with 20% representing overlap.  This can be help to       */
+/*      prevent small objects on a boundary from shifting too high      */
+/*      up the tree.                                                    */
+/* -------------------------------------------------------------------- */
+
+#define SHP_SPLIT_RATIO	0.55
+
+/************************************************************************/
+/*                             SfRealloc()                              */
+/*                                                                      */
+/*      A realloc cover function that will access a NULL pointer as     */
+/*      a valid input.                                                  */
+/************************************************************************/
+
+static void * SfRealloc( void * pMem, int nNewSize )
+
+{
+    if( pMem == NULL )
+        return( (void *) malloc(nNewSize) );
+    else
+        return( (void *) realloc(pMem,nNewSize) );
+}
+
+/************************************************************************/
+/*                          SHPTreeNodeInit()                           */
+/*                                                                      */
+/*      Initialize a tree node.                                         */
+/************************************************************************/
+
+static SHPTreeNode *SHPTreeNodeCreate( double * padfBoundsMin,
+                                       double * padfBoundsMax )
+
+{
+    SHPTreeNode	*psTreeNode;
+
+    psTreeNode = (SHPTreeNode *) malloc(sizeof(SHPTreeNode));
+
+    psTreeNode->nShapeCount = 0;
+    psTreeNode->panShapeIds = NULL;
+    psTreeNode->papsShapeObj = NULL;
+
+    psTreeNode->nSubNodes = 0;
+
+    if( padfBoundsMin != NULL )
+        memcpy( psTreeNode->adfBoundsMin, padfBoundsMin, sizeof(double) * 4 );
+
+    if( padfBoundsMax != NULL )
+        memcpy( psTreeNode->adfBoundsMax, padfBoundsMax, sizeof(double) * 4 );
+
+    return psTreeNode;
+}
+
+
+/************************************************************************/
+/*                           SHPCreateTree()                            */
+/************************************************************************/
+
+SHPTree SHPAPI_CALL1(*)
+SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
+               double *padfBoundsMin, double *padfBoundsMax )
+
+{
+    SHPTree	*psTree;
+
+    if( padfBoundsMin == NULL && hSHP == NULL )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Allocate the tree object                                        */
+/* -------------------------------------------------------------------- */
+    psTree = (SHPTree *) malloc(sizeof(SHPTree));
+
+    psTree->hSHP = hSHP;
+    psTree->nMaxDepth = nMaxDepth;
+    psTree->nDimension = nDimension;
+
+/* -------------------------------------------------------------------- */
+/*      If no max depth was defined, try to select a reasonable one     */
+/*      that implies approximately 8 shapes per node.                   */
+/* -------------------------------------------------------------------- */
+    if( psTree->nMaxDepth == 0 && hSHP != NULL )
+    {
+        int	nMaxNodeCount = 1;
+        int	nShapeCount;
+
+        SHPGetInfo( hSHP, &nShapeCount, NULL, NULL, NULL );
+        while( nMaxNodeCount*4 < nShapeCount )
+        {
+            psTree->nMaxDepth += 1;
+            nMaxNodeCount = nMaxNodeCount * 2;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Allocate the root node.                                         */
+/* -------------------------------------------------------------------- */
+    psTree->psRoot = SHPTreeNodeCreate( padfBoundsMin, padfBoundsMax );
+
+/* -------------------------------------------------------------------- */
+/*      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.                      */
+/* -------------------------------------------------------------------- */
+    if( padfBoundsMin == NULL )
+    {
+        SHPGetInfo( hSHP, NULL, NULL,
+                    psTree->psRoot->adfBoundsMin, 
+                    psTree->psRoot->adfBoundsMax );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If we have a file, insert all it's shapes into the tree.        */
+/* -------------------------------------------------------------------- */
+    if( hSHP != NULL )
+    {
+        int	iShape, nShapeCount;
+        
+        SHPGetInfo( hSHP, &nShapeCount, NULL, NULL, NULL );
+
+        for( iShape = 0; iShape < nShapeCount; iShape++ )
+        {
+            SHPObject	*psShape;
+            
+            psShape = SHPReadObject( hSHP, iShape );
+            SHPTreeAddShapeId( psTree, psShape );
+            SHPDestroyObject( psShape );
+        }
+    }        
+
+    return psTree;
+}
+
+/************************************************************************/
+/*                         SHPDestroyTreeNode()                         */
+/************************************************************************/
+
+static void SHPDestroyTreeNode( SHPTreeNode * psTreeNode )
+
+{
+    int		i;
+    
+    for( i = 0; i < psTreeNode->nSubNodes; i++ )
+    {
+        if( psTreeNode->apsSubNode[i] != NULL )
+            SHPDestroyTreeNode( psTreeNode->apsSubNode[i] );
+    }
+    
+    if( psTreeNode->panShapeIds != NULL )
+        free( psTreeNode->panShapeIds );
+
+    if( psTreeNode->papsShapeObj != NULL )
+    {
+        for( i = 0; i < psTreeNode->nShapeCount; i++ )
+        {
+            if( psTreeNode->papsShapeObj[i] != NULL )
+                SHPDestroyObject( psTreeNode->papsShapeObj[i] );
+        }
+
+        free( psTreeNode->papsShapeObj );
+    }
+
+    free( psTreeNode );
+}
+
+/************************************************************************/
+/*                           SHPDestroyTree()                           */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPDestroyTree( SHPTree * psTree )
+
+{
+    SHPDestroyTreeNode( psTree->psRoot );
+    free( psTree );
+}
+
+/************************************************************************/
+/*                       SHPCheckBoundsOverlap()                        */
+/*                                                                      */
+/*      Do the given boxes overlap at all?                              */
+/************************************************************************/
+
+int SHPAPI_CALL
+SHPCheckBoundsOverlap( double * padfBox1Min, double * padfBox1Max,
+                       double * padfBox2Min, double * padfBox2Max,
+                       int nDimension )
+
+{
+    int		iDim;
+
+    for( iDim = 0; iDim < nDimension; iDim++ )
+    {
+        if( padfBox2Max[iDim] < padfBox1Min[iDim] )
+            return FALSE;
+        
+        if( padfBox1Max[iDim] < padfBox2Min[iDim] )
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                      SHPCheckObjectContained()                       */
+/*                                                                      */
+/*      Does the given shape fit within the indicated extents?          */
+/************************************************************************/
+
+static int SHPCheckObjectContained( SHPObject * psObject, int nDimension,
+                           double * padfBoundsMin, double * padfBoundsMax )
+
+{
+    if( psObject->dfXMin < padfBoundsMin[0]
+        || psObject->dfXMax > padfBoundsMax[0] )
+        return FALSE;
+    
+    if( psObject->dfYMin < padfBoundsMin[1]
+        || psObject->dfYMax > padfBoundsMax[1] )
+        return FALSE;
+
+    if( nDimension == 2 )
+        return TRUE;
+    
+    if( psObject->dfZMin < padfBoundsMin[2]
+        || psObject->dfZMax < padfBoundsMax[2] )
+        return FALSE;
+        
+    if( nDimension == 3 )
+        return TRUE;
+
+    if( psObject->dfMMin < padfBoundsMin[3]
+        || psObject->dfMMax < padfBoundsMax[3] )
+        return FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         SHPTreeSplitBounds()                         */
+/*                                                                      */
+/*      Split a region into two subregion evenly, cutting along the     */
+/*      longest dimension.                                              */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPTreeSplitBounds( double *padfBoundsMinIn, double *padfBoundsMaxIn,
+                    double *padfBoundsMin1, double * padfBoundsMax1,
+                    double *padfBoundsMin2, double * padfBoundsMax2 )
+
+{
+/* -------------------------------------------------------------------- */
+/*      The output bounds will be very similar to the input bounds,     */
+/*      so just copy over to start.                                     */
+/* -------------------------------------------------------------------- */
+    memcpy( padfBoundsMin1, padfBoundsMinIn, sizeof(double) * 4 );
+    memcpy( padfBoundsMax1, padfBoundsMaxIn, sizeof(double) * 4 );
+    memcpy( padfBoundsMin2, padfBoundsMinIn, sizeof(double) * 4 );
+    memcpy( padfBoundsMax2, padfBoundsMaxIn, sizeof(double) * 4 );
+    
+/* -------------------------------------------------------------------- */
+/*      Split in X direction.                                           */
+/* -------------------------------------------------------------------- */
+    if( (padfBoundsMaxIn[0] - padfBoundsMinIn[0])
+        			> (padfBoundsMaxIn[1] - padfBoundsMinIn[1]) )
+    {
+        double	dfRange = padfBoundsMaxIn[0] - padfBoundsMinIn[0];
+
+        padfBoundsMax1[0] = padfBoundsMinIn[0] + dfRange * SHP_SPLIT_RATIO;
+        padfBoundsMin2[0] = padfBoundsMaxIn[0] - dfRange * SHP_SPLIT_RATIO;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Otherwise split in Y direction.                                 */
+/* -------------------------------------------------------------------- */
+    else
+    {
+        double	dfRange = padfBoundsMaxIn[1] - padfBoundsMinIn[1];
+
+        padfBoundsMax1[1] = padfBoundsMinIn[1] + dfRange * SHP_SPLIT_RATIO;
+        padfBoundsMin2[1] = padfBoundsMaxIn[1] - dfRange * SHP_SPLIT_RATIO;
+    }
+}
+
+/************************************************************************/
+/*                       SHPTreeNodeAddShapeId()                        */
+/************************************************************************/
+
+static int
+SHPTreeNodeAddShapeId( SHPTreeNode * psTreeNode, SHPObject * psObject,
+                       int nMaxDepth, int nDimension )
+
+{
+    int		i;
+    
+/* -------------------------------------------------------------------- */
+/*      If there are subnodes, then consider wiether this object        */
+/*      will fit in them.                                               */
+/* -------------------------------------------------------------------- */
+    if( nMaxDepth > 1 && psTreeNode->nSubNodes > 0 )
+    {
+        for( i = 0; i < psTreeNode->nSubNodes; i++ )
+        {
+            if( SHPCheckObjectContained(psObject, nDimension,
+                                      psTreeNode->apsSubNode[i]->adfBoundsMin,
+                                      psTreeNode->apsSubNode[i]->adfBoundsMax))
+            {
+                return SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[i],
+                                              psObject, nMaxDepth-1,
+                                              nDimension );
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Otherwise, consider creating four subnodes if could fit into    */
+/*      them, and adding to the appropriate subnode.                    */
+/* -------------------------------------------------------------------- */
+#if MAX_SUBNODE == 4
+    else if( nMaxDepth > 1 && psTreeNode->nSubNodes == 0 )
+    {
+        double	adfBoundsMinH1[4], adfBoundsMaxH1[4];
+        double	adfBoundsMinH2[4], adfBoundsMaxH2[4];
+        double	adfBoundsMin1[4], adfBoundsMax1[4];
+        double	adfBoundsMin2[4], adfBoundsMax2[4];
+        double	adfBoundsMin3[4], adfBoundsMax3[4];
+        double	adfBoundsMin4[4], adfBoundsMax4[4];
+
+        SHPTreeSplitBounds( psTreeNode->adfBoundsMin,
+                            psTreeNode->adfBoundsMax,
+                            adfBoundsMinH1, adfBoundsMaxH1,
+                            adfBoundsMinH2, adfBoundsMaxH2 );
+
+        SHPTreeSplitBounds( adfBoundsMinH1, adfBoundsMaxH1,
+                            adfBoundsMin1, adfBoundsMax1,
+                            adfBoundsMin2, adfBoundsMax2 );
+
+        SHPTreeSplitBounds( adfBoundsMinH2, adfBoundsMaxH2,
+                            adfBoundsMin3, adfBoundsMax3,
+                            adfBoundsMin4, adfBoundsMax4 );
+
+        if( SHPCheckObjectContained(psObject, nDimension,
+                                    adfBoundsMin1, adfBoundsMax1)
+            || SHPCheckObjectContained(psObject, nDimension,
+                                    adfBoundsMin2, adfBoundsMax2)
+            || SHPCheckObjectContained(psObject, nDimension,
+                                    adfBoundsMin3, adfBoundsMax3)
+            || SHPCheckObjectContained(psObject, nDimension,
+                                    adfBoundsMin4, adfBoundsMax4) )
+        {
+            psTreeNode->nSubNodes = 4;
+            psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
+                                                           adfBoundsMax1 );
+            psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
+                                                           adfBoundsMax2 );
+            psTreeNode->apsSubNode[2] = SHPTreeNodeCreate( adfBoundsMin3,
+                                                           adfBoundsMax3 );
+            psTreeNode->apsSubNode[3] = SHPTreeNodeCreate( adfBoundsMin4,
+                                                           adfBoundsMax4 );
+
+            /* recurse back on this node now that it has subnodes */
+            return( SHPTreeNodeAddShapeId( psTreeNode, psObject,
+                                           nMaxDepth, nDimension ) );
+        }
+    }
+#endif /* MAX_SUBNODE == 4 */
+
+/* -------------------------------------------------------------------- */
+/*      Otherwise, consider creating two subnodes if could fit into     */
+/*      them, and adding to the appropriate subnode.                    */
+/* -------------------------------------------------------------------- */
+#if MAX_SUBNODE == 2
+    else if( nMaxDepth > 1 && psTreeNode->nSubNodes == 0 )
+    {
+        double	adfBoundsMin1[4], adfBoundsMax1[4];
+        double	adfBoundsMin2[4], adfBoundsMax2[4];
+
+        SHPTreeSplitBounds( psTreeNode->adfBoundsMin, psTreeNode->adfBoundsMax,
+                            adfBoundsMin1, adfBoundsMax1,
+                            adfBoundsMin2, adfBoundsMax2 );
+
+        if( SHPCheckObjectContained(psObject, nDimension,
+                                 adfBoundsMin1, adfBoundsMax1))
+        {
+            psTreeNode->nSubNodes = 2;
+            psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
+                                                           adfBoundsMax1 );
+            psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
+                                                           adfBoundsMax2 );
+
+            return( SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[0], psObject,
+                                           nMaxDepth - 1, nDimension ) );
+        }
+        else if( SHPCheckObjectContained(psObject, nDimension,
+                                         adfBoundsMin2, adfBoundsMax2) )
+        {
+            psTreeNode->nSubNodes = 2;
+            psTreeNode->apsSubNode[0] = SHPTreeNodeCreate( adfBoundsMin1,
+                                                           adfBoundsMax1 );
+            psTreeNode->apsSubNode[1] = SHPTreeNodeCreate( adfBoundsMin2,
+                                                           adfBoundsMax2 );
+
+            return( SHPTreeNodeAddShapeId( psTreeNode->apsSubNode[1], psObject,
+                                           nMaxDepth - 1, nDimension ) );
+        }
+    }
+#endif /* MAX_SUBNODE == 2 */
+
+/* -------------------------------------------------------------------- */
+/*      If none of that worked, just add it to this nodes list.         */
+/* -------------------------------------------------------------------- */
+    psTreeNode->nShapeCount++;
+
+    psTreeNode->panShapeIds =
+        SfRealloc( psTreeNode->panShapeIds,
+                   sizeof(int) * psTreeNode->nShapeCount );
+    psTreeNode->panShapeIds[psTreeNode->nShapeCount-1] = psObject->nShapeId;
+
+    if( psTreeNode->papsShapeObj != NULL )
+    {
+        psTreeNode->papsShapeObj =
+            SfRealloc( psTreeNode->papsShapeObj,
+                       sizeof(void *) * psTreeNode->nShapeCount );
+        psTreeNode->papsShapeObj[psTreeNode->nShapeCount-1] = NULL;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         SHPTreeAddShapeId()                          */
+/*                                                                      */
+/*      Add a shape to the tree, but don't keep a pointer to the        */
+/*      object data, just keep the shapeid.                             */
+/************************************************************************/
+
+int SHPAPI_CALL
+SHPTreeAddShapeId( SHPTree * psTree, SHPObject * psObject )
+
+{
+    return( SHPTreeNodeAddShapeId( psTree->psRoot, psObject,
+                                   psTree->nMaxDepth, psTree->nDimension ) );
+}
+
+/************************************************************************/
+/*                      SHPTreeCollectShapesIds()                       */
+/*                                                                      */
+/*      Work function implementing SHPTreeFindLikelyShapes() on a       */
+/*      tree node by tree node basis.                                   */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPTreeCollectShapeIds( SHPTree *hTree, SHPTreeNode * psTreeNode,
+                        double * padfBoundsMin, double * padfBoundsMax,
+                        int * pnShapeCount, int * pnMaxShapes,
+                        int ** ppanShapeList )
+
+{
+    int		i;
+    
+/* -------------------------------------------------------------------- */
+/*      Does this node overlap the area of interest at all?  If not,    */
+/*      return without adding to the list at all.                       */
+/* -------------------------------------------------------------------- */
+    if( !SHPCheckBoundsOverlap( psTreeNode->adfBoundsMin,
+                                psTreeNode->adfBoundsMax,
+                                padfBoundsMin,
+                                padfBoundsMax,
+                                hTree->nDimension ) )
+        return;
+
+/* -------------------------------------------------------------------- */
+/*      Grow the list to hold the shapes on this node.                  */
+/* -------------------------------------------------------------------- */
+    if( *pnShapeCount + psTreeNode->nShapeCount > *pnMaxShapes )
+    {
+        *pnMaxShapes = (*pnShapeCount + psTreeNode->nShapeCount) * 2 + 20;
+        *ppanShapeList = (int *)
+            SfRealloc(*ppanShapeList,sizeof(int) * *pnMaxShapes);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Add the local nodes shapeids to the list.                       */
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < psTreeNode->nShapeCount; i++ )
+    {
+        (*ppanShapeList)[(*pnShapeCount)++] = psTreeNode->panShapeIds[i];
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      Recurse to subnodes if they exist.                              */
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < psTreeNode->nSubNodes; i++ )
+    {
+        if( psTreeNode->apsSubNode[i] != NULL )
+            SHPTreeCollectShapeIds( hTree, psTreeNode->apsSubNode[i],
+                                    padfBoundsMin, padfBoundsMax,
+                                    pnShapeCount, pnMaxShapes,
+                                    ppanShapeList );
+    }
+}
+
+/************************************************************************/
+/*                      SHPTreeFindLikelyShapes()                       */
+/*                                                                      */
+/*      Find all shapes within tree nodes for which the tree node       */
+/*      bounding box overlaps the search box.  The return value is      */
+/*      an array of shapeids terminated by a -1.  The shapeids will     */
+/*      be in order, as hopefully this will result in faster (more      */
+/*      sequential) reading from the file.                              */
+/************************************************************************/
+
+/* helper for qsort */
+static int
+compare_ints( const void * a, const void * b)
+{
+    return (*(int*)a) - (*(int*)b);
+}
+
+int SHPAPI_CALL1(*)
+SHPTreeFindLikelyShapes( SHPTree * hTree,
+                         double * padfBoundsMin, double * padfBoundsMax,
+                         int * pnShapeCount )
+
+{
+    int	*panShapeList=NULL, nMaxShapes = 0;
+
+/* -------------------------------------------------------------------- */
+/*      Perform the search by recursive descent.                        */
+/* -------------------------------------------------------------------- */
+    *pnShapeCount = 0;
+
+    SHPTreeCollectShapeIds( hTree, hTree->psRoot,
+                            padfBoundsMin, padfBoundsMax,
+                            pnShapeCount, &nMaxShapes,
+                            &panShapeList );
+
+/* -------------------------------------------------------------------- */
+/*      Sort the id array                                               */
+/* -------------------------------------------------------------------- */
+
+    qsort(panShapeList, *pnShapeCount, sizeof(int), compare_ints);
+
+    return panShapeList;
+}
+
+/************************************************************************/
+/*                          SHPTreeNodeTrim()                           */
+/*                                                                      */
+/*      This is the recurve version of SHPTreeTrimExtraNodes() that     */
+/*      walks the tree cleaning it up.                                  */
+/************************************************************************/
+
+static int SHPTreeNodeTrim( SHPTreeNode * psTreeNode )
+
+{
+    int		i;
+
+/* -------------------------------------------------------------------- */
+/*      Trim subtrees, and free subnodes that come back empty.          */
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < psTreeNode->nSubNodes; i++ )
+    {
+        if( SHPTreeNodeTrim( psTreeNode->apsSubNode[i] ) )
+        {
+            SHPDestroyTreeNode( psTreeNode->apsSubNode[i] );
+
+            psTreeNode->apsSubNode[i] =
+                psTreeNode->apsSubNode[psTreeNode->nSubNodes-1];
+
+            psTreeNode->nSubNodes--;
+
+            i--; /* process the new occupant of this subnode entry */
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      We should be trimmed if we have no subnodes, and no shapes.     */
+/* -------------------------------------------------------------------- */
+    return( psTreeNode->nSubNodes == 0 && psTreeNode->nShapeCount == 0 );
+}
+
+/************************************************************************/
+/*                       SHPTreeTrimExtraNodes()                        */
+/*                                                                      */
+/*      Trim empty nodes from the tree.  Note that we never trim an     */
+/*      empty root node.                                                */
+/************************************************************************/
+
+void SHPAPI_CALL
+SHPTreeTrimExtraNodes( SHPTree * hTree )
+
+{
+    SHPTreeNodeTrim( hTree->psRoot );
+}
+

Added: packages/thuban/branches/upstream/current/libraries/thuban/gdalwarp.cpp
===================================================================
--- packages/thuban/branches/upstream/current/libraries/thuban/gdalwarp.cpp	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/thuban/gdalwarp.cpp	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1232 @@
+/******************************************************************************
+ * $Id: gdalwarp.cpp 2712 2006-10-15 23:27:05Z bernhard $
+ *
+ * Project:  High Performance Image Reprojector
+ * Purpose:  Test program for high performance warper API.
+ * Author:   Frank Warmerdam <warmerdam at pobox.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, i3 - information integration and imaging 
+ *                          Fort Collin, CO
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ * $Log$
+ * Revision 1.9  2005/02/18 21:22:53  jonathan
+ * Optimize the loop in gdalwarp which builds a mask. Handle the majority of an
+ * image in a loop, creating 8 bits at a time. Later, handle the edge case where
+ * less than 8 bits are packed.
+ *
+ * Revision 1.8  2005/02/18 14:54:17  jonathan
+ * Refactored baserenderer.py and renderer.py to remove baserenderer.py's
+ * dependencies on wxPython. Added a new method projected_raster_layer()
+ * that returns a raster layer image in projected space. This must be
+ * implemented in classes derived from BaseRenderer. This also eliminates
+ * the dependency on gdal in baserenderer.py.
+ *
+ * Revision 1.7  2005/02/16 21:14:47  jonathan
+ * Further wxPython 2.5 changes using patches from Daniel Calvelo Aros
+ * so that that wxproj doesn't crash. Added GUI support for selecting
+ * alpha channel (opacity can't be selected yet).
+ *
+ * Revision 1.6  2005/02/07 19:51:13  jonathan
+ * Removed unnecessary/unused macros.
+ *
+ * Revision 1.5  2005/01/28 19:10:07  jonathan
+ * Recoded how the mask is packed into the bit array.
+ *
+ * Revision 1.4  2005/01/28 15:54:00  jonathan
+ * Make layer's use_mask flag default to true. Support a bit array describing
+ * the mask to use. Improve error handling in ProjectRasterFile (also addresses
+ * RT #2947).
+ *
+ * Revision 1.3  2005/01/27 14:17:01  jonathan
+ * Replace the old gdalwarp.cpp code with the non-simple version supplied with
+ * gdal. This allows added features such as creating an alpha band.
+ *
+ * Revision 1.13  2004/11/14 04:57:04  fwarmerdam
+ * added -srcalpha switch, and automatic alpha detection
+ *
+ * Revision 1.12  2004/11/05 06:15:08  fwarmerdam
+ * Don't double free the warpoptions array.
+ *
+ * Revision 1.11  2004/11/05 05:53:43  fwarmerdam
+ * Avoid various memory leaks.
+ *
+ * Revision 1.10  2004/10/07 15:53:42  fwarmerdam
+ * added preliminary alpha band support
+ *
+ * Revision 1.9  2004/08/31 19:58:57  warmerda
+ * Added error check if dst srs given but no source srs available.
+ * http://208.24.120.44/show_bug.cgi?id=603
+ *
+ * Revision 1.8  2004/08/11 21:10:29  warmerda
+ * Removed extra dumpopendatasets call.
+ *
+ * Revision 1.7  2004/08/11 20:11:24  warmerda
+ * Added special VRT mode
+ *
+ * Revision 1.6  2004/07/28 17:56:00  warmerda
+ * use return instead of exit() to avoid lame warnings on windows
+ *
+ * Revision 1.5  2004/04/02 17:33:22  warmerda
+ * added GDALGeneralCmdLineProcessor()
+ *
+ * Revision 1.4  2004/04/01 19:51:18  warmerda
+ * Added the -dstnodata commandline switch.
+ *
+ * Revision 1.3  2004/03/17 05:49:26  warmerda
+ * Fixed assert check in GDALWarpCreateOutput().
+ *
+ * Revision 1.2  2003/09/19 17:52:21  warmerda
+ * removed planned -gcp option
+ *
+ * Revision 1.1  2003/09/19 17:40:46  warmerda
+ * Renamed from gdalwarptest.cpp to gdalwarp.cpp, replacing old gdalwarp. 
+ *
+ * Revision 1.12  2003/07/04 11:53:14  dron
+ * Added `-rcs' option to select bicubic B-spline resampling.
+ *
+ * Revision 1.11  2003/06/05 16:55:42  warmerda
+ * enable INIT_DEST=0 by default when creating new files
+ *
+ * Revision 1.10  2003/05/28 18:18:43  warmerda
+ * added -q (quiet) flag
+ *
+ * Revision 1.9  2003/05/21 14:40:40  warmerda
+ * fix error message
+ *
+ * Revision 1.8  2003/05/20 18:35:38  warmerda
+ * added error reporting if SRS import fails
+ *
+ * Revision 1.7  2003/05/06 18:11:29  warmerda
+ * added -multi in usage
+ *
+ * Revision 1.6  2003/04/23 05:18:02  warmerda
+ * added -multi switch
+ *
+ * Revision 1.5  2003/04/21 17:21:04  warmerda
+ * Fixed -wm switch.
+ *
+ * Revision 1.4  2003/03/28 17:43:04  warmerda
+ * added -wm option to control warp memory
+ *
+ * Revision 1.3  2003/03/18 17:37:44  warmerda
+ * add color table copying
+ *
+ * Revision 1.2  2003/03/02 05:24:02  warmerda
+ * added -srcnodata option
+ *
+ * Revision 1.1  2003/02/22 02:03:41  warmerda
+ * New
+ *
+ */
+
+#include <locale.h>
+
+#include <Python.h>
+
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "gdal_priv.h"
+#include "gdalwarper.h"
+#include "cpl_string.h"
+#include "ogr_srs_api.h"
+
+#define PYTHON_CPL_ERR(x) \
+    {const char *str = CPLGetLastErrorMsg(); \
+        str != NULL ? PyErr_SetString(x, str) : PyErr_SetString(x, "");}
+
+#define LEAVE_NOW(e) { err = e; goto getOut; }
+
+#define OPTS_MASK  1
+#define OPTS_ALPHA 2
+#define OPTS_INVERT_MASK_BITS 4
+
+CPL_CVSID("$Id: gdalwarp.cpp 2712 2006-10-15 23:27:05Z bernhard $");
+
+static GDALDatasetH 
+GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename, 
+                      const char *pszFormat, const char *pszSourceSRS, 
+                      const char *pszTargetSRS, int nOrder, 
+                      char **papszCreateOptions, GDALDataType eDT );
+static PyObject* get_gdal_version(PyObject *, PyObject * args);
+static PyObject* ProjectRasterFile(PyObject *, PyObject * args);
+
+static double	       dfMinX=0.0, dfMinY=0.0, dfMaxX=0.0, dfMaxY=0.0;
+static double	       dfXRes=0.0, dfYRes=0.0;
+static int             nForcePixels=0, nForceLines=0;
+static int             bEnableDstAlpha = FALSE, bEnableSrcAlpha = FALSE;
+static int             bMakeMask, bMakeAlpha, bInvertMask;
+const char             *pszSrcFilename = NULL, *pszDstFilename = "MEM:::";
+
+static PyMethodDef gdalwarp_methods[] = {
+    { "ProjectRasterFile", ProjectRasterFile, METH_VARARGS },
+    { "get_gdal_version", get_gdal_version, METH_VARARGS },
+    {NULL, NULL}
+};
+
+/************************************************************************/
+/*                          get_gdal_version                            */
+/************************************************************************/
+static PyObject*
+get_gdal_version(PyObject *, PyObject * args)
+{
+    PyObject *version = PyString_FromString(GDALVersionInfo("RELEASE_NAME"));
+
+    Py_XINCREF(version);
+
+    return version;
+}
+
+/************************************************************************/
+/*                            initgdalwarp                              */
+/************************************************************************/
+#ifdef __cplusplus
+extern "C"
+#endif
+void initgdalwarp(void)
+{
+    PyObject * shapelib = NULL;
+    PyObject * c_api_func = NULL;
+    PyObject * cobj = NULL;
+                                                                                
+    Py_InitModule("gdalwarp", gdalwarp_methods);
+                                                                                
+    Py_XDECREF(cobj);
+    Py_XDECREF(c_api_func);
+    Py_XDECREF(shapelib);
+}
+
+/************************************************************************/
+/*                             SanitizeSRS                              */
+/************************************************************************/
+
+char *SanitizeSRS( const char *pszUserInput )
+
+{
+    OGRSpatialReferenceH hSRS;
+    char *pszResult = NULL;
+
+    CPLErrorReset();
+
+    hSRS = OSRNewSpatialReference( NULL );
+    if( OSRSetFromUserInput( hSRS, pszUserInput ) == OGRERR_NONE )
+        OSRExportToWkt( hSRS, &pszResult );
+#if 0
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Translating source or target SRS failed:\n%s",
+                  pszUserInput );
+        exit( 1 );
+    }
+#endif
+    
+    OSRDestroySpatialReference( hSRS );
+
+    return pszResult;
+}
+
+/************************************************************************/
+/*                             GetImageData                             */
+/*                                                                      */ 
+/* Extract the image data from the GDALDataset and pack it into a single*/
+/* array of RGB triples. Use the ColorTable to determine the RGB        */
+/* values. We extract the data from the GDALDataset rather than create  */
+/* our own driver because the data needs to be translated from          */
+/* 4 byte pixel information into 3 byte RGB information. This could be  */
+/* done as the data is written to the data set or afterwards, as it is  */
+/* done here. Any minor savings from our own driver are outweighed by   */
+/* the high development/maintenance costs.                              */
+/*                                                                      */ 
+/************************************************************************/
+
+static CPLErr GetImageData(GDALDataset *ds, 
+                           unsigned char **imgbuf, 
+                           unsigned int   *imglen,
+                           unsigned char **maskbuf, 
+                           unsigned int   *masklen) 
+{
+    CPLErr ret = CE_None;
+
+    GDALColorTable *pal = NULL;
+
+
+    ds->FlushCache();
+
+    int rasterCount  = ds->GetRasterCount();
+    int nRasterXSize = ds->GetRasterXSize();
+    int nRasterYSize = ds->GetRasterYSize();
+    if ( ! (nRasterXSize > 0 && nRasterYSize > 0 ))
+    {
+        PyErr_Format(PyExc_ValueError, 
+                "The dimensions (%ix%i) are invalid in %s", 
+                nRasterXSize, nRasterYSize, pszSrcFilename);
+        return CE_Failure;
+    }
+
+    //
+    // create the new image array for RGBRGB... values
+    //
+    *imglen = 3 * nRasterXSize * nRasterYSize;
+    *imgbuf = (unsigned char*)CPLMalloc(*imglen);
+    if ( *imgbuf == NULL ) 
+    {
+        PyErr_Format(PyExc_MemoryError, 
+                "The system does not have enough memory to project %s", 
+                pszSrcFilename);
+        return CE_Failure;
+    }
+
+    //
+    // if there are three or more bands assume that the first three
+    // are for RGB, unless told otherwise 
+    //
+    if (rasterCount >= 3)
+    {
+        for (int i=1; i <= 3; i++)
+        {
+            int offs = 0;
+            GDALRasterBand *band = ds->GetRasterBand(i);
+
+            switch (band->GetColorInterpretation())
+            {
+                case GCI_Undefined: offs = i-1; break;
+                case GCI_RedBand:   offs = 1; break;
+                case GCI_GreenBand: offs = 2; break;
+                case GCI_BlueBand:  offs = 3; break;
+                default:            offs = -1; break;
+            }
+
+            //
+            // copy the image into the buffer using the proper offset
+            // so we first copy over all Red values, then all Green
+            // values, and then all Blue values
+            //
+
+            if (0 <= offs && offs < 3)
+            {
+                ret = band->RasterIO(GF_Read, 0, 0, 
+                                     nRasterXSize, nRasterYSize,
+                                     *imgbuf+offs, nRasterXSize, nRasterYSize, 
+                                     GDT_Byte, 3, 0);
+                if (ret == CE_Failure)
+                {
+                    PyErr_Format(PyExc_IOError, 
+                        "An unknown error occured while reading band %i in %s",
+                        i, pszSrcFilename);
+                    break;
+                }
+            }
+        }
+    }
+    else if (rasterCount >= 1)
+    {
+        //
+        // one band is either a palette based image, or greyscale
+        //
+
+        GDALRasterBand *band = ds->GetRasterBand(1);
+
+        switch (band->GetColorInterpretation())
+        {
+            case GCI_PaletteIndex:
+
+                pal = band->GetColorTable();
+                
+                if (pal == NULL)
+                {
+                    PyErr_Format(PyExc_IOError, 
+                        "Couldn't find a palette for palette-based image %s", 
+                        pszSrcFilename);
+                    ret = CE_Failure;
+                }
+                else
+                {
+                    GDALPaletteInterp pal_interp 
+                        = pal->GetPaletteInterpretation();
+
+                    //
+                    // copy over all the palette indices and then
+                    // loop through the buffer replacing the values
+                    // with the correct RGB triples. 
+                    //
+                    ret = band->RasterIO(GF_Read, 0, 0, 
+                                         nRasterXSize, nRasterYSize,
+                                         *imgbuf, nRasterXSize, nRasterYSize, 
+                                         GDT_UInt16, 3, 0);
+                            
+                    if (ret == CE_Failure) 
+                    {
+                        PyErr_Format(PyExc_IOError, 
+                            "An unknown error occured while reading band 1 in %s", pszSrcFilename);
+                        break;
+                    }
+
+                    for (unsigned char *data = *imgbuf;
+                         data != (*imgbuf+*imglen);
+                         data += 3)
+                    {
+
+                        unsigned short int val = *((unsigned short int *)data);
+
+                        const GDALColorEntry *color = pal->GetColorEntry(val);
+
+                        if (pal_interp == GPI_Gray)
+                        {
+                            *(data + 0) = color->c1;
+                            *(data + 1) = color->c1;
+                            *(data + 2) = color->c1;
+                        }
+                        else
+                        {
+                            *(data + 0) = color->c1;
+                            *(data + 1) = color->c2;
+                            *(data + 2) = color->c3;
+                        }
+                    }
+                }
+                break;
+
+            case GCI_Undefined: // can we try to make a greyscale image?
+            case GCI_GrayIndex:
+
+                //
+                // copy over all the palette indices and then
+                // loop through the buffer replacing the values
+                // with the correct RGB triples. 
+                //
+                ret = band->RasterIO(GF_Read, 0, 0, 
+                                     nRasterXSize, nRasterYSize,
+                                     *imgbuf, nRasterXSize, nRasterYSize, 
+                                     GDT_Byte, 3, 0);
+                        
+                if (ret == CE_Failure) 
+                {
+                    PyErr_Format(PyExc_IOError, 
+                        "An unknown error occured while reading band 1 in %s", 
+                        pszSrcFilename);
+                    break;
+                }
+
+                for (unsigned char *data = *imgbuf;
+                     data != (*imgbuf+*imglen);
+                     data += 3)
+                {
+                    //pal->GetColorEntry(*data, &color);
+
+                    //*(data + 0) = *data; // already correct
+                    *(data + 1) = *data;
+                    *(data + 2) = *data;
+                }
+                break;
+
+            default:
+                PyErr_Format(PyExc_ValueError, 
+                    "Unsupported color interpretation '%s' in image %s", 
+                    GDALGetColorInterpretationName(
+                        band->GetColorInterpretation()),
+                    pszSrcFilename);
+
+                ret = CE_Failure;
+                break;
+        }
+    }
+    else
+    {
+        PyErr_Format(PyExc_ValueError, 
+                  "Unsupported number of raster bands (%i) in image %s\n",
+                  rasterCount, pszSrcFilename);
+
+        ret = CE_Failure;
+    }
+
+    if (ret == CE_None && bEnableDstAlpha && rasterCount > 1)
+    {
+        if (bMakeMask)
+        {
+            //
+            // The mask is really an XBM image. In other words, each
+            // pixel is represented by one bit in a byte array.
+            //
+            // First read the alpha band, and then convert it to
+            // a bit array by thresholding each pixel value at 128.
+            //
+            
+            *masklen = ((nRasterXSize + 7) / 8) * nRasterYSize;
+            *maskbuf = (unsigned char *)CPLMalloc(*masklen);
+
+            if ( *maskbuf != NULL )
+            {
+                unsigned char *tmp 
+                    = (unsigned char *)CPLMalloc(nRasterXSize * nRasterYSize);
+
+                if ( tmp == NULL )
+                {
+                    CPLFree(*maskbuf);
+                    *maskbuf = NULL;
+                }
+                else
+                {
+                    GDALRasterBand *band = ds->GetRasterBand(rasterCount);
+
+                    ret = band->RasterIO(GF_Read, 0, 0, 
+                                         nRasterXSize, nRasterYSize,
+                                         tmp, nRasterXSize, nRasterYSize, 
+                                         GDT_Byte, 0, 0);
+
+                    if (ret != CE_Failure)
+                    {
+                        int i, j, b=1, c=0;
+                        unsigned char *ptr = *maskbuf;
+                        unsigned char *tptr = tmp;
+
+                        //unsigned int empty_count=0;
+
+                        for (i=0; i < nRasterYSize; i++)
+                        {
+                            for (j=nRasterXSize; j >= 8; j -= 8)
+                            {
+                                c=0; b=1;
+                                if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                
+                                if (bInvertMask) 
+                                    *(ptr++) = ~c;
+                                else
+                                    *(ptr++) = c;
+                            }
+
+                            c=0; b=1;
+                            switch (nRasterXSize & 7)
+                            {
+                                case 7: if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                case 6: if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                case 5: if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                case 4: if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                case 3: if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                case 2: if (*tptr++ >= 128) {c|=b;} b<<=1;
+                                case 1: 
+                                    if (*tptr++ >= 128) {c|=b;} 
+                                    b<<=1;
+
+                                    //
+                                    // byte should be padded with 0's so
+                                    // it's not a simple inversion
+                                    //
+                                    if (bInvertMask) 
+                                        *(ptr++) = ~c & (b-1);
+                                    else
+                                        *(ptr++) = c;
+
+                                default: break;
+                            }
+                        }
+
+#if 0
+                        if (empty_count == *masklen)
+                        {
+                            fprintf(stderr, "mask not used\n");
+
+                            CPLFree(*maskbuf);
+                            *maskbuf = NULL;
+                        }
+#endif
+                    }
+
+                    CPLFree(tmp);
+                    tmp = NULL;
+                }
+
+            }
+        }
+        else if (bMakeAlpha)
+        {
+            //
+            // This is the simple case. The array we get back from RasterIO
+            // is already in the correct format.
+            //
+            
+            *masklen = nRasterXSize * nRasterYSize;
+            *maskbuf = (unsigned char *)CPLMalloc(*masklen);
+
+            if ( *maskbuf != NULL )
+            {
+                GDALRasterBand *band = ds->GetRasterBand(rasterCount);
+
+                ret = band->RasterIO(GF_Read, 0, 0, 
+                                     nRasterXSize, nRasterYSize,
+                                     *maskbuf, nRasterXSize, nRasterYSize, 
+                                     GDT_Byte, 0, 0);
+
+#if 0
+                if (ret == CE_Failure)
+                {
+                    CPLFree(*maskbuf);
+                    *maskbuf = NULL;
+                }
+#endif
+            }
+        }
+    }
+
+    if (ret != CE_None) 
+    {
+        if (*imgbuf  != NULL) { CPLFree(*imgbuf);  *imgbuf  = NULL; }
+        if (*maskbuf != NULL) { CPLFree(*maskbuf); *maskbuf = NULL; }
+    }
+
+    return ret;
+}
+
+/************************************************************************/
+/*                          ProjectRasterFile                           */
+/************************************************************************/
+
+static PyObject*
+ProjectRasterFile(PyObject *, PyObject * args)
+{
+    GDALDatasetH	hSrcDS=NULL, hDstDS=NULL;
+    const char         *pszFormat = "MEM";
+    char               *pszTargetSRS = NULL;
+    char               *pszSourceSRS = NULL;
+    int                 bCreateOutput = FALSE, i, nOrder = 0;
+    void               *hTransformArg, *hGenImgProjArg=NULL, *hApproxArg=NULL;
+    char               **papszWarpOptions = NULL;
+    double             dfErrorThreshold = 0.125;
+    double             dfWarpMemoryLimit = 0.0;
+    GDALTransformerFunc pfnTransformer = NULL;
+    char                **papszCreateOptions = NULL;
+    GDALDataType        eOutputType = GDT_Unknown, eWorkingType = GDT_Unknown; 
+    GDALResampleAlg     eResampleAlg = GRA_NearestNeighbour;
+    int                 bMulti = FALSE;
+    int                 err = 0;
+    unsigned char      *imgbuf = NULL;
+    unsigned int        imglen = 0;
+    unsigned char      *maskbuf = NULL;
+    unsigned int        masklen = 0;
+    int                 options = 0;
+
+    char * 		savedlocale = NULL;
+
+    GDALWarpOperation oWO;
+    GDALWarpOptions *psWO = NULL;
+
+    PyObject * pyImageData = NULL;
+    PyObject * pyMaskData = NULL;
+    PyObject * filename;
+    PyObject * srcImageArgs;
+    PyObject * dstImageArgs;
+    PyObject * extents;
+    PyObject * resolution;
+    PyObject * imageRes;
+    PyObject * opts;
+    PyObject * pyReturnData = NULL;
+
+
+    if (!PyArg_ParseTuple(args, "OOOOOOO", &filename, &srcImageArgs, 
+                &dstImageArgs, 
+                &extents, 
+                &resolution, &imageRes,
+                &opts))
+    {
+        return NULL;
+    }
+
+    dfXRes=0.0; dfYRes=0.0;
+
+    pszSrcFilename = PyString_AsString( filename );
+
+#   if PY_VERSION_HEX >=0x02040000
+	/* python before 2.4 only called modules with LC_NUMERIC "C". 
+	 * so we only need to act for >=2.4 */
+        savedlocale = setlocale( LC_NUMERIC, NULL );
+        if (! setlocale( LC_NUMERIC, "C" ))
+        {
+            PyErr_SetString(PyExc_ValueError, 
+	    	"Could not switch to locale \"C\".");
+	    /* did not open anything, so no need to jump to getOut */
+	    return NULL;
+        }
+#   endif
+
+    pszSourceSRS = SanitizeSRS( PyString_AsString( srcImageArgs ) );
+    pszTargetSRS = SanitizeSRS( PyString_AsString( dstImageArgs ) );
+
+    dfMinX = PyFloat_AsDouble( PyTuple_GetItem( extents, 0 ) );
+    dfMinY = PyFloat_AsDouble( PyTuple_GetItem( extents, 1 ) );
+    dfMaxX = PyFloat_AsDouble( PyTuple_GetItem( extents, 2 ) );
+    dfMaxY = PyFloat_AsDouble( PyTuple_GetItem( extents, 3 ) );
+
+    nForcePixels = ( int )PyInt_AsLong( PyTuple_GetItem( imageRes, 0 ) );
+    nForceLines  = ( int )PyInt_AsLong( PyTuple_GetItem( imageRes, 1 ) );
+
+    options  = ( int )PyInt_AsLong( opts );
+    bMakeMask  = (options & OPTS_MASK) == OPTS_MASK;
+    bMakeAlpha = (options & OPTS_ALPHA) == OPTS_ALPHA;
+    bInvertMask = (options & OPTS_INVERT_MASK_BITS) == OPTS_INVERT_MASK_BITS;
+
+    // FIXME: error if bMakeMask == bMaskAlpha
+
+    bEnableDstAlpha = bMakeMask || bMakeAlpha;
+
+    GDALAllRegister();
+
+/* -------------------------------------------------------------------- */
+/*      Open source dataset.                                            */
+/* -------------------------------------------------------------------- */
+    hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
+    
+    if( hSrcDS == NULL )
+    {
+        PYTHON_CPL_ERR( PyExc_IOError );
+        LEAVE_NOW( CPLGetLastErrorNo() );
+    }
+
+    if( pszSourceSRS == NULL )
+    {
+        if( GDALGetProjectionRef( hSrcDS ) != NULL 
+            && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
+            pszSourceSRS = CPLStrdup(GDALGetProjectionRef( hSrcDS ));
+
+        else if( GDALGetGCPProjection( hSrcDS ) != NULL
+                 && strlen(GDALGetGCPProjection(hSrcDS)) > 0 
+                 && GDALGetGCPCount( hSrcDS ) > 1 )
+            pszSourceSRS = CPLStrdup(GDALGetGCPProjection( hSrcDS ));
+        else
+            pszSourceSRS = CPLStrdup("");
+    }
+
+    if( pszTargetSRS != NULL && strlen(pszSourceSRS) == 0 )
+    {
+        PyErr_Format(PyExc_ValueError, 
+            "A target projection was specified, "
+            "but there is no source projection in %s", pszSrcFilename );
+        LEAVE_NOW( 1 );
+    }
+
+    if( pszTargetSRS == NULL )
+        pszTargetSRS = CPLStrdup(pszSourceSRS);
+
+    if( GDALGetRasterColorInterpretation( 
+            GDALGetRasterBand(hSrcDS,GDALGetRasterCount(hSrcDS)) ) 
+        == GCI_AlphaBand 
+        && !bEnableSrcAlpha )
+    {
+        bEnableSrcAlpha = TRUE;
+#if 0
+        printf( "Using band %d of source image as alpha.\n", 
+                GDALGetRasterCount(hSrcDS) );
+#endif
+    }
+        
+
+/* -------------------------------------------------------------------- */
+/*      If not, we need to create it.                                   */
+/* -------------------------------------------------------------------- */
+    if( hDstDS == NULL )
+    {
+        hDstDS = GDALWarpCreateOutput( hSrcDS, pszDstFilename, pszFormat, 
+                                       pszSourceSRS, pszTargetSRS, nOrder,
+                                       papszCreateOptions, eOutputType );
+        bCreateOutput = TRUE;
+
+        papszWarpOptions = CSLSetNameValue(papszWarpOptions, "INIT_DEST", "0");
+
+        CSLDestroy( papszCreateOptions );
+        papszCreateOptions = NULL;
+    }
+
+    if( hDstDS == NULL )
+    {
+        PyErr_Format(PyExc_IOError, 
+            "Error creating destination image for projecting %s",
+            pszSrcFilename);
+        LEAVE_NOW( CPLE_FileIO );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a transformation object from the source to               */
+/*      destination coordinate system.                                  */
+/* -------------------------------------------------------------------- */
+    hTransformArg = hGenImgProjArg = 
+        GDALCreateGenImgProjTransformer( hSrcDS, pszSourceSRS, 
+                                         hDstDS, pszTargetSRS, 
+                                         TRUE, 1000.0, nOrder );
+
+
+    if( hTransformArg == NULL )
+    {
+        PYTHON_CPL_ERR(PyExc_ValueError );
+        LEAVE_NOW( CPLE_IllegalArg );
+    }
+
+    pfnTransformer = GDALGenImgProjTransform;
+
+    CPLFree( pszSourceSRS );
+    pszSourceSRS = NULL;
+
+    CPLFree( pszTargetSRS );
+    pszTargetSRS = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Warp the transformer with a linear approximator unless the      */
+/*      acceptable error is zero.                                       */
+/* -------------------------------------------------------------------- */
+    if( dfErrorThreshold != 0.0 )
+    {
+        hTransformArg = hApproxArg = 
+            GDALCreateApproxTransformer( GDALGenImgProjTransform, 
+                                         hGenImgProjArg, dfErrorThreshold );
+        pfnTransformer = GDALApproxTransform;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Setup warp options.                                             */
+/* -------------------------------------------------------------------- */
+    psWO = GDALCreateWarpOptions();
+
+    psWO->papszWarpOptions = papszWarpOptions;
+    psWO->eWorkingDataType = eWorkingType;
+    psWO->eResampleAlg = eResampleAlg;
+
+    psWO->hSrcDS = hSrcDS;
+    psWO->hDstDS = hDstDS;
+
+    psWO->pfnTransformer = pfnTransformer;
+    psWO->pTransformerArg = hTransformArg;
+
+    if( dfWarpMemoryLimit != 0.0 )
+        psWO->dfWarpMemoryLimit = dfWarpMemoryLimit;
+
+/* -------------------------------------------------------------------- */
+/*      Setup band mapping.                                             */
+/* -------------------------------------------------------------------- */
+    if( bEnableSrcAlpha )
+        psWO->nBandCount = GDALGetRasterCount(hSrcDS) - 1;
+    else
+        psWO->nBandCount = GDALGetRasterCount(hSrcDS);
+
+    psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
+    psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
+
+    for( i = 0; i < psWO->nBandCount; i++ )
+    {
+        psWO->panSrcBands[i] = i+1;
+        psWO->panDstBands[i] = i+1;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Setup alpha bands used if any.                                  */
+/* -------------------------------------------------------------------- */
+    if( bEnableSrcAlpha )
+        psWO->nSrcAlphaBand = GDALGetRasterCount(hSrcDS);
+
+    if( !bEnableDstAlpha 
+        && GDALGetRasterCount(hDstDS) == psWO->nBandCount+1 
+        && GDALGetRasterColorInterpretation( 
+            GDALGetRasterBand(hDstDS,GDALGetRasterCount(hDstDS))) 
+        == GCI_AlphaBand )
+    {
+#if 0
+        printf( "Using band %d of destination image as alpha.\n", 
+                GDALGetRasterCount(hDstDS) );
+#endif
+                
+        bEnableDstAlpha = TRUE;
+    }
+
+    if( bEnableDstAlpha )
+        psWO->nDstAlphaBand = GDALGetRasterCount(hDstDS);
+
+/* -------------------------------------------------------------------- */
+/*      Setup NODATA options.                                           */
+/* -------------------------------------------------------------------- */
+#if 0
+    if( pszSrcNodata != NULL )
+    {
+        char **papszTokens = CSLTokenizeString( pszSrcNodata );
+        int  nTokenCount = CSLCount(papszTokens);
+
+        psWO->padfSrcNoDataReal = (double *) 
+            CPLMalloc(psWO->nBandCount*sizeof(double));
+        psWO->padfSrcNoDataImag = (double *) 
+            CPLMalloc(psWO->nBandCount*sizeof(double));
+
+        for( i = 0; i < psWO->nBandCount; i++ )
+        {
+            if( i < nTokenCount )
+            {
+                CPLStringToComplex( papszTokens[i], 
+                                    psWO->padfSrcNoDataReal + i,
+                                    psWO->padfSrcNoDataImag + i );
+            }
+            else
+            {
+                psWO->padfSrcNoDataReal[i] = psWO->padfSrcNoDataReal[i-1];
+                psWO->padfSrcNoDataImag[i] = psWO->padfSrcNoDataImag[i-1];
+            }
+        }
+
+        CSLDestroy( papszTokens );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If the output dataset was created, and we have a destination    */
+/*      nodata value, go through marking the bands with the information.*/
+/* -------------------------------------------------------------------- */
+    if( pszDstNodata != NULL && bCreateOutput )
+    {
+        char **papszTokens = CSLTokenizeString( pszDstNodata );
+        int  nTokenCount = CSLCount(papszTokens);
+
+        psWO->padfDstNoDataReal = (double *) 
+            CPLMalloc(psWO->nBandCount*sizeof(double));
+        psWO->padfDstNoDataImag = (double *) 
+            CPLMalloc(psWO->nBandCount*sizeof(double));
+
+        for( i = 0; i < psWO->nBandCount; i++ )
+        {
+            if( i < nTokenCount )
+            {
+                CPLStringToComplex( papszTokens[i], 
+                                    psWO->padfDstNoDataReal + i,
+                                    psWO->padfDstNoDataImag + i );
+            }
+            else
+            {
+                psWO->padfDstNoDataReal[i] = psWO->padfDstNoDataReal[i-1];
+                psWO->padfDstNoDataImag[i] = psWO->padfDstNoDataImag[i-1];
+            }
+
+            if( bCreateOutput )
+            {
+                GDALSetRasterNoDataValue( 
+                    GDALGetRasterBand( hDstDS, psWO->panDstBands[i] ), 
+                    psWO->padfDstNoDataReal[i] );
+            }
+        }
+
+        CSLDestroy( papszTokens );
+    }
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Initialize and execute the warp.                                */
+/* -------------------------------------------------------------------- */
+
+    if( oWO.Initialize( psWO ) == CE_None )
+    {
+        if( bMulti )
+            oWO.ChunkAndWarpMulti( 0, 0, 
+                                   GDALGetRasterXSize( hDstDS ),
+                                   GDALGetRasterYSize( hDstDS ) );
+        else
+            oWO.ChunkAndWarpImage( 0, 0, 
+                                   GDALGetRasterXSize( hDstDS ),
+                                   GDALGetRasterYSize( hDstDS ) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+    if( hApproxArg != NULL )
+        GDALDestroyApproxTransformer( hApproxArg );
+
+    if( hGenImgProjArg != NULL )
+        GDALDestroyGenImgProjTransformer( hGenImgProjArg );
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup.                                                        */
+/* -------------------------------------------------------------------- */
+    CPLErrorReset();
+    err = 0;
+
+    imglen = 0;
+    imgbuf = NULL;
+    masklen = 0;
+    maskbuf = NULL;
+
+    if ( GetImageData((GDALDataset *)hDstDS, 
+                      &imgbuf, &imglen, &maskbuf, &masklen) == CE_None)
+    {
+        pyImageData = PyString_FromStringAndSize( ( char * )imgbuf,  imglen);
+
+        pyReturnData = PyTuple_New(3);
+        PyTuple_SetItem(pyReturnData, 0, pyImageData);
+
+        if (bMakeAlpha && maskbuf != NULL)
+        {
+            pyMaskData = PyString_FromStringAndSize( ( char * )maskbuf,masklen);
+            PyTuple_SetItem(pyReturnData, 1, Py_None);
+            PyTuple_SetItem(pyReturnData, 2, pyMaskData);
+        }
+        else if (bMakeMask && maskbuf != NULL)
+        {
+            pyMaskData = PyString_FromStringAndSize( ( char * )maskbuf,masklen);
+            PyTuple_SetItem(pyReturnData, 1, pyMaskData);
+            PyTuple_SetItem(pyReturnData, 2, Py_None);
+        }
+        else
+        {
+            PyTuple_SetItem(pyReturnData, 1, Py_None);
+            PyTuple_SetItem(pyReturnData, 2, Py_None);
+        }
+
+        if (imgbuf  != NULL) { CPLFree(imgbuf);  imgbuf  = NULL; }
+        if (maskbuf != NULL) { CPLFree(maskbuf); maskbuf = NULL; }
+
+    }
+
+getOut:
+
+    GDALClose( hDstDS );
+    GDALClose( hSrcDS );
+
+    if (psWO != NULL) GDALDestroyWarpOptions( psWO );
+
+    //GDALDumpOpenDatasets( stderr );
+
+    GDALDestroyDriverManager();
+
+#   if PY_VERSION_HEX >=0x02040000
+        if (savedlocale)
+	    setlocale( LC_NUMERIC, savedlocale);
+#   endif
+    
+    if ( !err && CPLGetLastErrorNo() )
+    {
+        PYTHON_CPL_ERR( PyExc_StandardError );
+        return NULL;
+    }
+
+    if ( err ) 
+    {
+        return NULL;
+    }
+    else
+    {
+        return pyReturnData;
+    }
+}
+
+/************************************************************************/
+/*                        GDALWarpCreateOutput()                        */
+/*                                                                      */
+/*      Create the output file based on various commandline options,    */
+/*      and the input file.                                             */
+/************************************************************************/
+
+static GDALDatasetH 
+GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename, 
+                      const char *pszFormat, const char *pszSourceSRS, 
+                      const char *pszTargetSRS, int nOrder,
+                      char **papszCreateOptions, GDALDataType eDT )
+
+
+{
+    GDALDriverH hDriver;
+    GDALDatasetH hDstDS;
+    void *hTransformArg;
+    double adfDstGeoTransform[6];
+    int nPixels=0, nLines=0;
+
+    CPLErrorReset();
+
+    if( eDT == GDT_Unknown )
+        eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1));
+
+/* -------------------------------------------------------------------- */
+/*      Find the output driver.                                         */
+/* -------------------------------------------------------------------- */
+    hDriver = GDALGetDriverByName( pszFormat );
+    if( hDriver == NULL 
+        || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
+    {
+#if 0
+        int	iDr;
+        
+        printf( "Output driver `%s' not recognised or does not support\n", 
+                pszFormat );
+        printf( "direct output file creation.  The following format drivers are configured\n"
+                "and support direct output:\n" );
+
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        {
+            GDALDriverH hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
+            {
+                printf( "  %s: %s\n",
+                        GDALGetDriverShortName( hDriver  ),
+                        GDALGetDriverLongName( hDriver ) );
+            }
+        }
+        printf( "\n" );
+#endif
+
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a transformation object from the source to               */
+/*      destination coordinate system.                                  */
+/* -------------------------------------------------------------------- */
+    hTransformArg = 
+        GDALCreateGenImgProjTransformer( hSrcDS, pszSourceSRS, 
+                                         NULL, pszTargetSRS, 
+                                         TRUE, 1000.0, nOrder );
+
+    if( hTransformArg == NULL )
+        return NULL;
+
+    //
+    // This could happen if the proj library didn't load correctly
+    // Fixes RF#2947
+    //
+    if (CPLGetLastErrorNo() != CE_None)
+    {
+        GDALDestroyGenImgProjTransformer(hTransformArg);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get approximate output definition.                              */
+/* -------------------------------------------------------------------- */
+    if( GDALSuggestedWarpOutput( hSrcDS, 
+                                 GDALGenImgProjTransform, hTransformArg, 
+                                 adfDstGeoTransform, &nPixels, &nLines )
+        != CE_None )
+        return NULL;
+
+    GDALDestroyGenImgProjTransformer( hTransformArg );
+
+/* -------------------------------------------------------------------- */
+/*      Did the user override some parameters?                          */
+/* -------------------------------------------------------------------- */
+    if( dfXRes != 0.0 && dfYRes != 0.0 )
+    {
+        CPLAssert( nForcePixels == 0 && nForceLines == 0 );
+        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
+        {
+            dfMinX = adfDstGeoTransform[0];
+            dfMaxX = adfDstGeoTransform[0] + adfDstGeoTransform[1] * nPixels;
+            dfMaxY = adfDstGeoTransform[3];
+            dfMinY = adfDstGeoTransform[3] + adfDstGeoTransform[5] * nLines;
+        }
+
+        nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
+        nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
+        adfDstGeoTransform[0] = dfMinX;
+        adfDstGeoTransform[3] = dfMaxY;
+        adfDstGeoTransform[1] = dfXRes;
+        adfDstGeoTransform[5] = -dfYRes;
+    }
+
+    else if( nForcePixels != 0 && nForceLines != 0 )
+    {
+        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
+        {
+            dfMinX = adfDstGeoTransform[0];
+            dfMaxX = adfDstGeoTransform[0] + adfDstGeoTransform[1] * nPixels;
+            dfMaxY = adfDstGeoTransform[3];
+            dfMinY = adfDstGeoTransform[3] + adfDstGeoTransform[5] * nLines;
+        }
+
+        dfXRes = (dfMaxX - dfMinX) / nForcePixels;
+        dfYRes = (dfMaxY - dfMinY) / nForceLines;
+
+        adfDstGeoTransform[0] = dfMinX;
+        adfDstGeoTransform[3] = dfMaxY;
+        adfDstGeoTransform[1] = dfXRes;
+        adfDstGeoTransform[5] = -dfYRes;
+
+        nPixels = nForcePixels;
+        nLines = nForceLines;
+    }
+
+    else if( dfMinX != 0.0 || dfMinY != 0.0 || dfMaxX != 0.0 || dfMaxY != 0.0 )
+    {
+        dfXRes = adfDstGeoTransform[1];
+        dfYRes = fabs(adfDstGeoTransform[5]);
+
+        nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
+        nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
+
+        adfDstGeoTransform[0] = dfMinX;
+        adfDstGeoTransform[3] = dfMaxY;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we want to generate an alpha band in the output file?        */
+/* -------------------------------------------------------------------- */
+    int nDstBandCount = GDALGetRasterCount(hSrcDS);
+
+    if( bEnableSrcAlpha )
+        nDstBandCount--;
+
+    if( bEnableDstAlpha )
+        nDstBandCount++;
+
+/* -------------------------------------------------------------------- */
+/*      Create the output file.                                         */
+/* -------------------------------------------------------------------- */
+    hDstDS = GDALCreate( hDriver, pszFilename, nPixels, nLines, 
+                         nDstBandCount, eDT, papszCreateOptions );
+    
+    if( hDstDS == NULL )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Write out the projection definition.                            */
+/* -------------------------------------------------------------------- */
+    GDALSetProjection( hDstDS, pszTargetSRS );
+    GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
+
+/* -------------------------------------------------------------------- */
+/*      Try to set color interpretation of output file alpha band.      */
+/*      TODO: We should likely try to copy the other bands too.         */
+/* -------------------------------------------------------------------- */
+    if( bEnableDstAlpha )
+    {
+        GDALSetRasterColorInterpretation( 
+            GDALGetRasterBand( hDstDS, nDstBandCount ), 
+            GCI_AlphaBand );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Copy the color table, if required.                              */
+/* -------------------------------------------------------------------- */
+    GDALColorTableH hCT;
+
+    hCT = GDALGetRasterColorTable( GDALGetRasterBand(hSrcDS,1) );
+    if( hCT != NULL )
+        GDALSetRasterColorTable( GDALGetRasterBand(hDstDS,1), hCT );
+
+    return hDstDS;
+}
+    

Added: packages/thuban/branches/upstream/current/libraries/thuban/swigPtrConvertHack.h
===================================================================
--- packages/thuban/branches/upstream/current/libraries/thuban/swigPtrConvertHack.h	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/thuban/swigPtrConvertHack.h	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,123 @@
+#ifndef __WXHACK_H
+#define __WXHACK_H
+
+#include <wx/wx.h>
+
+/* helper function to extract the pointer value from a swig ptr string
+ * as used in wxPython 2.4
+ */
+static void *
+decode_pointer(char *string)
+{
+  unsigned long p = 0;
+
+  /* Pointer values must start with leading underscore */
+  if (*string == '_')
+  {
+      string++;
+      /* Extract hex value from pointer */
+      while (*string)
+      {
+	  if ((*string >= '0') && (*string <= '9'))
+	    p = (p << 4) + (*string - '0');
+	  else if ((*string >= 'a') && (*string <= 'f'))
+	    p = (p << 4) + ((*string - 'a') + 10);
+	  else
+	    break;
+	  string++;
+      }
+  }
+  return (void*)p;
+}
+
+/* helper function to extract the pointer value from a swig ptr string
+ * as used in wxPython 2.5
+ *
+ * The hexvalues describe the bytes making up the pointer in memory,
+ * i.e. when the pointer is considered as an array of bytes (we assume
+ * char==byte in the implementation).  In the older version it was
+ * always a bigendian representation.
+ */
+static void*
+decode_pointer_new(char *string, unsigned int length)
+{
+    void * p = 0;
+    unsigned char *pp = (unsigned char*)&p;
+    unsigned int count = 0;
+
+    /* sanity check: the string must be at least as long as twice the
+     * size of the pointer (two hex digits per byte) plus one for the
+     * initial underscore */
+    if (length < 2 * sizeof(p) + 1)
+	return NULL;
+
+    /* Pointer values must start with leading underscore */
+    if (*string == '_')
+    {
+	string++;
+	length--;
+
+	/* the remaining length must be at least twice as long as the
+	 * size of the pointer. */
+
+	/* now decode the hex values.  We decode exactly two bytes for
+	 * each of the bytes in the pointer */
+	while (count < 2 * sizeof(p))
+	{
+	    if ((*string >= '0') && (*string <= '9'))
+		*pp = (*pp << 4) + (*string - '0');
+	    else if ((*string >= 'a') && (*string <= 'f'))
+		*pp = (*pp << 4) + ((*string - 'a') + 10);
+	    else
+		break;
+	    string++;
+	    count++;
+	    if (count % 2 == 0)
+		pp++;
+	}
+  }
+  return p;
+}
+
+/* Return the object wrapped by the SWIG shadow object shadow
+ *
+ * The pointer to the real object can be decoded from the "this"
+ * attribute of the python object.  In wxPython 2.4 it's a string
+ * containing a hex representation of the pointer value.  In wxPython
+ * 2.5 it's a special python object which can nevertheless be converted
+ * to a string with a hex representation of the pointer value which is a
+ * bit different than the one for 2.4.
+ */
+bool
+wxPyConvertSwigPtr(PyObject* obj, void **ptr, const wxChar* className)
+{
+    PyObject * string = NULL;
+    PyObject * thisobject = NULL;
+
+    *ptr = 0;
+
+    thisobject = PyObject_GetAttrString(obj, "this");
+    if (thisobject)
+    {
+	if (!PyString_Check(thisobject))
+	{
+	    string = PyObject_Str(thisobject);
+	    if (string)
+	    {
+		*ptr = decode_pointer_new(PyString_AsString(string),
+					  PyString_Size(string));
+		Py_DECREF(string);
+	    }
+	}
+	else
+	{
+	    *ptr = decode_pointer(PyString_AsString(thisobject));
+	}
+    }
+
+    Py_XDECREF(thisobject);
+
+    return *ptr != 0;
+}
+
+#endif

Added: packages/thuban/branches/upstream/current/libraries/thuban/wxPython_int.h
===================================================================
--- packages/thuban/branches/upstream/current/libraries/thuban/wxPython_int.h	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/thuban/wxPython_int.h	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,302 @@
+////////////////////////////////////////////////////////////////////////////
+// Name:        wxPython_int.h   (int == internal)
+// Purpose:     Helper functions/classes for the wxPython extension module
+//              This header should only be inclued directly by those source
+//              modules included in the wx._core module.  All others should
+//              include wx/wxPython/wxPython.h instead.
+//
+// Author:      Robin Dunn
+//
+// Created:     1-July-1997
+// RCS-ID:      $Id: wxPython_int.h 2562 2005-02-16 21:14:47Z jonathan $
+// Copyright:   (c) 1998 by Total Control Software
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __wxp_helpers__
+#define __wxp_helpers__
+
+#include <wx/wx.h>
+
+#if 1
+#include <wx/busyinfo.h>
+#include <wx/caret.h>
+//#include <wx/choicebk.h>
+#include <wx/clipbrd.h>
+#include <wx/colordlg.h>
+#include <wx/config.h>
+#include <wx/cshelp.h>
+//#include <wx/dcmirror.h>
+#include <wx/dcps.h>
+#include <wx/dirctrl.h>
+#include <wx/dirdlg.h>
+#include <wx/dnd.h>
+#include <wx/docview.h>
+#include <wx/encconv.h>
+#include <wx/fdrepdlg.h>
+#include <wx/fileconf.h>
+#include <wx/filesys.h>
+#include <wx/fontdlg.h>
+#include <wx/fs_inet.h>
+#include <wx/fs_mem.h>
+#include <wx/fs_zip.h>
+//#include <wx/gbsizer.h>
+#include <wx/geometry.h>
+//#include <wx/htmllbox.h>
+#include <wx/image.h>
+#include <wx/imaglist.h>
+#include <wx/intl.h>
+#include <wx/laywin.h>
+//#include <wx/listbook.h>
+#include <wx/minifram.h>
+#include <wx/notebook.h>
+#include <wx/print.h>
+#include <wx/printdlg.h>
+#include <wx/process.h>
+#include <wx/progdlg.h>
+#include <wx/sashwin.h>
+#include <wx/spinbutt.h>
+#include <wx/spinctrl.h>
+#include <wx/splash.h>
+#include <wx/splitter.h>
+#include <wx/statline.h>
+#include <wx/stream.h>
+#include <wx/sysopt.h>
+#include <wx/taskbar.h>
+#include <wx/tglbtn.h>
+#include <wx/tipwin.h>
+#include <wx/tooltip.h>
+//#include <wx/vlbox.h>
+//#include <wx/vscroll.h>
+#endif
+
+typedef unsigned char byte;
+typedef wxPoint2DDouble wxPoint2D;    
+//---------------------------------------------------------------------------
+
+// A macro that will help to execute simple statments wrapped in
+// StartBlock/EndBlockThreads calls
+#define wxPyBLOCK_THREADS(stmt) \
+    { bool blocked = wxPyBeginBlockThreads(); stmt; wxPyEndBlockThreads(blocked); }
+
+// Raise the NotImplementedError exception  (blocking threads)
+#define wxPyRaiseNotImplemented() \
+    wxPyBLOCK_THREADS(PyErr_SetNone(PyExc_NotImplementedError))
+
+// Raise any exception witha string value  (blocking threads)
+#define wxPyErr_SetString(err, str) \
+    wxPyBLOCK_THREADS(PyErr_SetString(err, str))
+
+
+//---------------------------------------------------------------------------
+
+#if PYTHON_API_VERSION < 1009
+#define PySequence_Fast_GET_ITEM(o, i) \
+     (PyList_Check(o) ? PyList_GET_ITEM(o, i) : PyTuple_GET_ITEM(o, i))
+#endif
+
+#define RETURN_NONE()                 { Py_INCREF(Py_None); return Py_None; }
+#define DECLARE_DEF_STRING(name)      static const wxString wxPy##name(wx##name)
+#define DECLARE_DEF_STRING2(name,val) static const wxString wxPy##name(val)
+
+//---------------------------------------------------------------------------
+
+#ifndef wxPyUSE_EXPORTED_API
+
+class wxPyCallback : public wxObject {
+    DECLARE_ABSTRACT_CLASS(wxPyCallback);
+public:
+    wxPyCallback(PyObject* func);
+    wxPyCallback(const wxPyCallback& other);
+    ~wxPyCallback();
+
+    void EventThunker(wxEvent& event);
+
+    PyObject*   m_func;
+};
+
+#endif // wxPyUSE_EXPORTED_API
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+// These Event classes can be derived from in Python and passed through the
+// event system without loosing anything.  They do this by keeping a reference
+// to themselves and some special case handling in wxPyCallback::EventThunker.
+
+
+
+class wxPyEvtSelfRef {
+public:
+    wxPyEvtSelfRef();
+    ~wxPyEvtSelfRef();
+
+    void SetSelf(PyObject* self, bool clone=false);
+    PyObject* GetSelf() const;
+    bool GetCloned() const { return m_cloned; }
+
+protected:
+    PyObject*   m_self;
+    bool        m_cloned;
+};
+
+
+class wxPyEvent : public wxEvent, public wxPyEvtSelfRef {
+    DECLARE_ABSTRACT_CLASS(wxPyEvent)
+public:
+    wxPyEvent(int winid=0, wxEventType commandType = wxEVT_NULL);
+    wxPyEvent(const wxPyEvent& evt);
+    ~wxPyEvent();
+
+    virtual wxEvent* Clone() const { return new wxPyEvent(*this); }
+};
+
+
+class wxPyCommandEvent : public wxCommandEvent, public wxPyEvtSelfRef {
+    DECLARE_ABSTRACT_CLASS(wxPyCommandEvent)
+public:
+    wxPyCommandEvent(wxEventType commandType = wxEVT_NULL, int id=0);
+    wxPyCommandEvent(const wxPyCommandEvent& evt);
+    ~wxPyCommandEvent();
+
+    virtual wxEvent* Clone() const { return new wxPyCommandEvent(*this); }
+};
+
+
+
+//----------------------------------------------------------------------
+// Forward decalre a few things used in the exported API
+class wxPyClientData;
+class wxPyUserData;
+class wxPyOORClientData;
+class wxPyCBInputStream;
+
+void wxPyClientData_dtor(wxPyClientData* self);
+void wxPyUserData_dtor(wxPyUserData* self);
+void wxPyOORClientData_dtor(wxPyOORClientData* self);
+wxPyCBInputStream* wxPyCBInputStream_create(PyObject *py, bool block);
+
+
+//---------------------------------------------------------------------------
+// Export a C API in a struct.  Other modules will be able to load this from
+// the wx.core module and will then have safe access to these functions, even if
+// in another shared library.
+
+class wxPyCallbackHelper;
+struct swig_type_info;
+struct swig_const_info;
+
+typedef double (*py_objasdbl_conv)(PyObject *obj);
+
+// Make SunCC happy and make typedef's for these that are extern "C"
+typedef swig_type_info* (*p_SWIG_Python_TypeRegister_t)(swig_type_info *);
+typedef swig_type_info* (*p_SWIG_Python_TypeCheck_t)(char *c, swig_type_info *);
+typedef void*           (*p_SWIG_Python_TypeCast_t)(swig_type_info *, void *);
+typedef swig_type_info* (*p_SWIG_Python_TypeDynamicCast_t)(swig_type_info *, void **);
+typedef const char*     (*p_SWIG_Python_TypeName_t)(const swig_type_info *);
+typedef const char *    (*p_SWIG_Python_TypePrettyName_t)(const swig_type_info *);
+typedef swig_type_info* (*p_SWIG_Python_TypeQuery_t)(const char *);
+typedef void            (*p_SWIG_Python_TypeClientData_t)(swig_type_info *, void *);
+typedef PyObject*       (*p_SWIG_Python_newvarlink_t)(void);
+typedef void            (*p_SWIG_Python_addvarlink_t)(PyObject *, char *, PyObject *(*)(void), int (*)(PyObject *));
+typedef int             (*p_SWIG_Python_ConvertPtr_t)(PyObject *, void **, swig_type_info *, int);
+typedef int             (*p_SWIG_Python_ConvertPacked_t)(PyObject *, void *, int sz, swig_type_info *, int);
+typedef char*           (*p_SWIG_Python_PackData_t)(char *c, void *, int);
+typedef char*           (*p_SWIG_Python_UnpackData_t)(char *c, void *, int);
+typedef PyObject*       (*p_SWIG_Python_NewPointerObj_t)(void *, swig_type_info *,int own);
+typedef PyObject*       (*p_SWIG_Python_NewPackedObj_t)(void *, int sz, swig_type_info *);
+typedef void            (*p_SWIG_Python_InstallConstants_t)(PyObject *d, swig_const_info constants[]);
+typedef void*           (*p_SWIG_Python_MustGetPtr_t)(PyObject *, swig_type_info *, int, int);
+
+
+struct wxPyCoreAPI {
+
+    p_SWIG_Python_TypeRegister_t       p_SWIG_Python_TypeRegister;
+    p_SWIG_Python_TypeCheck_t          p_SWIG_Python_TypeCheck;
+    p_SWIG_Python_TypeCast_t           p_SWIG_Python_TypeCast;
+    p_SWIG_Python_TypeDynamicCast_t    p_SWIG_Python_TypeDynamicCast;
+    p_SWIG_Python_TypeName_t           p_SWIG_Python_TypeName;
+    p_SWIG_Python_TypePrettyName_t     p_SWIG_Python_TypePrettyName; 
+    p_SWIG_Python_TypeQuery_t          p_SWIG_Python_TypeQuery;
+    p_SWIG_Python_TypeClientData_t     p_SWIG_Python_TypeClientData;
+    p_SWIG_Python_newvarlink_t         p_SWIG_Python_newvarlink;
+    p_SWIG_Python_addvarlink_t         p_SWIG_Python_addvarlink;
+    p_SWIG_Python_ConvertPtr_t         p_SWIG_Python_ConvertPtr;
+    p_SWIG_Python_ConvertPacked_t      p_SWIG_Python_ConvertPacked;
+    p_SWIG_Python_PackData_t           p_SWIG_Python_PackData;
+    p_SWIG_Python_UnpackData_t         p_SWIG_Python_UnpackData;
+    p_SWIG_Python_NewPointerObj_t      p_SWIG_Python_NewPointerObj;
+    p_SWIG_Python_NewPackedObj_t       p_SWIG_Python_NewPackedObj;
+    p_SWIG_Python_InstallConstants_t   p_SWIG_Python_InstallConstants;
+    p_SWIG_Python_MustGetPtr_t         p_SWIG_Python_MustGetPtr;
+    
+    bool                (*p_wxPyCheckSwigType)(const wxChar* className);
+    PyObject*           (*p_wxPyConstructObject)(void* ptr, const wxChar* className, int setThisOwn);
+    bool                (*p_wxPyConvertSwigPtr)(PyObject* obj, void **ptr, const wxChar* className);
+    PyObject*           (*p_wxPyMakeSwigPtr)(void* ptr, const wxChar* className);
+        
+    PyThreadState*      (*p_wxPyBeginAllowThreads)();
+    void                (*p_wxPyEndAllowThreads)(PyThreadState* state);
+    bool                (*p_wxPyBeginBlockThreads)();
+    void                (*p_wxPyEndBlockThreads)(bool blocked);
+
+    PyObject*           (*p_wxPy_ConvertList)(wxListBase* list);
+
+    wxString*           (*p_wxString_in_helper)(PyObject* source);
+    wxString            (*p_Py2wxString)(PyObject* source);
+    PyObject*           (*p_wx2PyString)(const wxString& src);
+
+    byte*               (*p_byte_LIST_helper)(PyObject* source);
+    int*                (*p_int_LIST_helper)(PyObject* source);
+    long*               (*p_long_LIST_helper)(PyObject* source);
+    char**              (*p_string_LIST_helper)(PyObject* source);
+    wxPoint*            (*p_wxPoint_LIST_helper)(PyObject* source, int* npoints);
+    wxBitmap**          (*p_wxBitmap_LIST_helper)(PyObject* source);
+    wxString*           (*p_wxString_LIST_helper)(PyObject* source);
+    wxAcceleratorEntry* (*p_wxAcceleratorEntry_LIST_helper)(PyObject* source);
+
+    bool                (*p_wxSize_helper)(PyObject* source, wxSize** obj);
+    bool                (*p_wxPoint_helper)(PyObject* source, wxPoint** obj);
+    bool                (*p_wxRealPoint_helper)(PyObject* source, wxRealPoint** obj);
+    bool                (*p_wxRect_helper)(PyObject* source, wxRect** obj);
+    bool                (*p_wxColour_helper)(PyObject* source, wxColour** obj);
+    bool                (*p_wxPoint2D_helper)(PyObject* source, wxPoint2DDouble** obj);
+
+    
+    bool                (*p_wxPySimple_typecheck)(PyObject* source, const wxChar* classname, int seqLen);
+    bool                (*p_wxColour_typecheck)(PyObject* source);
+
+    void                (*p_wxPyCBH_setCallbackInfo)(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref);
+    bool                (*p_wxPyCBH_findCallback)(const wxPyCallbackHelper& cbh, const char* name);
+    int                 (*p_wxPyCBH_callCallback)(const wxPyCallbackHelper& cbh, PyObject* argTuple);
+    PyObject*           (*p_wxPyCBH_callCallbackObj)(const wxPyCallbackHelper& cbh, PyObject* argTuple);
+    void                (*p_wxPyCBH_delete)(wxPyCallbackHelper* cbh);
+
+    PyObject*           (*p_wxPyMake_wxObject)(wxObject* source, bool setThisOwn, bool checkEvtHandler);
+    PyObject*           (*p_wxPyMake_wxSizer)(wxSizer* source, bool setThisOwn);
+    void                (*p_wxPyPtrTypeMap_Add)(const char* commonName, const char* ptrName);
+    bool                (*p_wxPy2int_seq_helper)(PyObject* source, int* i1, int* i2);
+    bool                (*p_wxPy4int_seq_helper)(PyObject* source, int* i1, int* i2, int* i3, int* i4);
+    PyObject*           (*p_wxArrayString2PyList_helper)(const wxArrayString& arr);
+    PyObject*           (*p_wxArrayInt2PyList_helper)(const wxArrayInt& arr);
+
+    void                (*p_wxPyClientData_dtor)(wxPyClientData*);
+    void                (*p_wxPyUserData_dtor)(wxPyUserData*);
+    void                (*p_wxPyOORClientData_dtor)(wxPyOORClientData*);
+
+    wxPyCBInputStream*  (*p_wxPyCBInputStream_create)(PyObject *py, bool block);
+
+    bool                (*p_wxPyInstance_Check)(PyObject* obj);
+    bool                (*p_wxPySwigInstance_Check)(PyObject* obj);
+
+    bool                (*p_wxPyCheckForApp)();
+
+};
+
+
+#ifdef wxPyUSE_EXPORTED_API
+// Notice that this is static, not extern.  This is by design, each module
+// needs one, but doesn't have to use it.
+static wxPyCoreAPI* wxPyCoreAPIPtr = NULL;
+inline wxPyCoreAPI* wxPyGetCoreAPIPtr();
+#endif // wxPyUSE_EXPORTED_API
+
+#endif

Added: packages/thuban/branches/upstream/current/libraries/thuban/wxproj.cpp
===================================================================
--- packages/thuban/branches/upstream/current/libraries/thuban/wxproj.cpp	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/libraries/thuban/wxproj.cpp	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,772 @@
+/* Copyright (c) 2001, 2002, 2003, 2004, 2005 by Intevation GmbH
+ * Authors:
+ * Bernhard Herzog <bh at intevation.de>
+ *
+ * This program is free software under the GPL (>=v2)
+ * Read the file COPYING coming with Thuban for details.
+ */
+
+/* module to read a shape from a shapefile with shapelib, project the
+ * data with proj4 and draw it on a wxWindows DC
+ */
+
+#include <Python.h>
+
+#include <stdlib.h>
+#include <math.h>
+
+#include <shapefil.h>
+#include "pyshapelib_api.h"
+
+#include <proj_api.h>
+
+#include <wx/wx.h>
+
+
+/* By default we use the wxPython.h API to access wxPython's objects at
+ * the C++ level.  On some systems that's not available, so we offer a
+ * work-around with swigPtrConvertHack.h, but we only do so if the
+ * compiler explicitly defines USE_WX_PYTHON_SWIG_HACK.
+ */
+#ifndef USE_WX_PYTHON_SWIG_HACK
+#include <wx/wxPython/wxPython.h>
+
+/* Compatibility code to cope with wxPython.h from wxPython 2.4.
+ *
+ * Instead of wxPyConvertSwigPtr there's SWIG_GetPtrObj which has almost
+ * the same interface but is a little different.  So we define our own
+ * wxPyConvertSwigPtr if we're being compiled with wxPython 2.4.  We
+ * determine that by checking whether a macro wxPyConvertSwigPtr is
+ * defined.
+ *
+ * In wxPython 2.5 the last parameter, type, is of type wxChar* which
+ * may be a wchar_t* and thus incompatible with char* and it's value is
+ * slightly different (the one in 2.4 needs a few more characters
+ * appended and prefixed).  Fortunately, it's is always passed via wxT,
+ * a macro that we only use for the type parameter.  So redefine it to
+ * do nothing but add the pre- and suffixes necessary for 2.4.
+ */
+#ifndef wxPyConvertSwigPtr
+bool
+wxPyConvertSwigPtr(PyObject *obj, void **ptr, char *type)
+{
+    /* import the API ptr if it hasn't been imported yet */
+    if (wxPyCoreAPIPtr == NULL)
+	wxPyCoreAPI_IMPORT();
+
+    return SWIG_GetPtrObj(obj, ptr, type) == 0;
+}
+#undef wxT
+#define wxT(a) ("_" a "_p")
+#endif /* not wxPyConvertSwigPtr */
+
+#else /* USE_WX_PYTHON_SWIG_HACK */
+#include "swigPtrConvertHack.h"
+#endif /* USE_WX_PYTHON_SWIG_HACK */
+
+/* pyshapelib api pointer */
+static PyShapeLibAPI * pyshapelib_api;
+
+
+/* Extract a pointer from a python object that has a cobject method.
+ *
+ * Call the object's cobject method and if it returns a Py_CObject
+ * extract the pointer from it and write the it into *output and return
+ * true. If unsuccessful set a Python exception, do not modify *output
+ * and return false.
+ *
+ * If object is None, set *output will to NULL.
+ */
+template<class T>
+int
+extract_pointer(PyObject * object, T**output)
+{
+    void * value = NULL;
+    PyObject *cobject = NULL;
+    
+    if (Py_None == object)
+    {
+	value = NULL;
+    }
+    else
+    {
+	cobject = PyObject_CallMethod(object, "cobject", NULL);
+	if (!cobject)
+	    return 0;
+
+	/* now cobject should be a CObject containing the projPJ* pointer */
+	if (PyCObject_Check(cobject))
+	{
+	    value = PyCObject_AsVoidPtr(cobject);
+	}
+	else
+	{
+	    PyErr_SetString(PyExc_TypeError,
+			    "The projection must be either None, "
+			    "or an object whose cobject method "
+			    "returns a CObjecta cobject");
+	    Py_XDECREF(cobject);
+	    return 0;
+	}
+    }
+
+    *output = (T*)value;
+    return 1;
+}
+
+
+/* Project the point (x, y) with the projections forward and inverse and
+ * scale it with scalex, scaley and offset it by offx, offy and store in
+ * *xdest, and *ydest.
+ */
+static void
+project_point(double * xdest, double *ydest,
+	      projPJ* forward, projPJ* inverse,
+	      double scalex, double scaley, double offx, double offy,
+	      double x, double y)
+{
+    projUV proj_point;
+
+    proj_point.u = x; 
+    proj_point.v = y;
+
+    if (inverse)
+        proj_point = pj_inv(proj_point, inverse);
+
+    if (forward)
+    {
+	if (!inverse)
+	{
+	    /* If a map projection is used but no layer projection we
+	     * have to assume that the shapefille data is in geographic
+	     * coordinates. Thuban assumes that they're in degrees but
+	     * proj uses radians, so we have to convert explicitly. With
+	     * a layer projection, i.e. inverse, present we already have
+	     * the coordinates in radians.
+	     */
+	    proj_point.u *= DEG_TO_RAD;
+	    proj_point.v *= DEG_TO_RAD;
+	}
+        proj_point = pj_fwd(proj_point, forward);
+    }
+    else if (inverse)
+    {
+	/* if there's an inverse projection but no forward projection
+	 * the coordinates are now in radians, so we have to convert
+	 * them to degrees.
+	 */
+	proj_point.u *= RAD_TO_DEG;
+	proj_point.v *= RAD_TO_DEG;
+    }
+	
+
+    *xdest = (scalex * proj_point.u + offx);
+    *ydest = (scaley * proj_point.v + offy);
+}
+
+
+/* Return the projected points as a wxPoint array. The array returned
+ * has a length of num_vertices + num_parts - 1
+ *
+ * The return value is suitable as a parameter to DrawPolygon with a
+ * non-null brush so that the shape will be filled correctly, even
+ * shapes with holes or otherwise consisting of multiple parts. This is
+ * achieved by connecting the start/end points of the parts with lines
+ * in such a way that these lines are given twice, but in opposite
+ * directions. This trick works on both X11 and Windows 2000 (perhaps
+ * on other windows versions too). This trick is the reason why the
+ * returned array has num_vertices + num_parts - 1 items.
+ */
+static wxPoint *
+project_points(int num_vertices, int num_parts,
+	       double * xs, double * ys, int * part_start,
+	       projPJ* forward, projPJ* inverse,
+	       double scalex, double scaley, double offx, double offy)
+{
+    int i;
+    int num_points = num_vertices + num_parts - 1;
+    wxPoint* points = (wxPoint*)malloc(num_points * sizeof(wxPoint));
+    if (!points)
+    {
+	PyErr_NoMemory();
+	return NULL;
+    }
+
+    for (i = 0; i < num_vertices; i++)
+    {
+        double x, y;
+
+        project_point(&x, &y, forward, inverse,
+                      scalex, scaley, offx, offy,
+                      xs[i], ys[i]);
+        points[i].x = (int)x;
+        points[i].y = (int)y;
+    }
+
+    /* link all the parts so that we can draw a multipart polygon with
+     * one DrawPolgon call. If the points array as a whole is used for
+     * DrawPolgon, the connections between the start points of the
+     * subparts are already in the polygon, but only in one direction.
+     * Here we add the same connections, but in the opposite order and
+     * direction.
+     */
+    for (i = num_parts - 1; i > 0; i--)
+    {
+	points[num_vertices + num_parts - 1 - i] = points[part_start[i]];
+    }
+
+    return points;
+}
+
+/*
+ * Structure to hold common data for calls to draw_polygon_shape().
+ */
+struct s_draw_info
+{
+    PyObject * py_shapefile;
+    PyObject * py_forward;
+    PyObject * py_inverse;
+    PyObject * py_dc;
+    double scalex, scaley, offx, offy;
+    SHPHandle handle;
+    projPJ * forward;
+    projPJ * inverse;
+    wxDC * dc;
+};
+
+
+/* Free a draw info struct */
+static void
+free_draw_info(void * p_draw_info)
+{
+    s_draw_info * draw_info = (s_draw_info*)p_draw_info;
+    Py_XDECREF(draw_info->py_shapefile);
+    Py_XDECREF(draw_info->py_dc);
+    Py_XDECREF(draw_info->py_forward);
+    Py_XDECREF(draw_info->py_inverse);
+    delete draw_info;
+}
+
+
+/*
+ * Initialize the structure for drawing polygons. Call once for each
+ * layer and pass the return value to draw_polygon_shape.
+ */
+static PyObject *
+draw_polygon_init(PyObject *, PyObject * args)
+{
+    PyObject * py_shapefile;
+    PyObject * py_forward;
+    PyObject * py_inverse;
+    PyObject * py_dc;
+    double scalex, scaley, offx, offy;
+
+    if (!PyArg_ParseTuple(args, "OOOOdddd",
+			  &py_shapefile,
+                          &py_dc, &py_forward, &py_inverse,
+			  &scalex, &scaley, &offx, &offy))
+	return NULL;
+
+    s_draw_info * draw_info = new s_draw_info;
+
+    draw_info->py_shapefile = 0;
+    draw_info->py_dc = 0;
+    draw_info->py_forward = 0;
+    draw_info->py_inverse = 0;
+
+    draw_info->py_shapefile = py_shapefile;
+    Py_INCREF(draw_info->py_shapefile);
+    if (!extract_pointer(draw_info->py_shapefile, &draw_info->handle))
+	goto fail;
+
+    draw_info->py_dc = py_dc;
+    Py_INCREF(draw_info->py_dc);
+    if (!wxPyConvertSwigPtr( py_dc, (void**)&(draw_info->dc), wxT("wxDC") ))
+    {
+	    PyErr_SetString(PyExc_TypeError,
+			"third argument must be a wxDC instance");
+        goto fail;
+    }
+    
+    draw_info->py_forward = py_forward;
+    Py_INCREF(draw_info->py_forward);
+    if (!extract_pointer(draw_info->py_forward, &draw_info->forward))
+	    goto fail;
+	    
+    draw_info->py_inverse = py_inverse;
+    Py_INCREF(draw_info->py_inverse);
+    if (!extract_pointer(draw_info->py_inverse, &draw_info->inverse))
+	goto fail;
+
+    draw_info->scalex = scalex;
+    draw_info->scaley = scaley;
+    draw_info->offx = offx;
+    draw_info->offy = offy;
+
+    return PyCObject_FromVoidPtr(draw_info, free_draw_info);
+
+ fail:
+    free_draw_info(draw_info);
+    return NULL;
+}
+
+
+/*
+ * Draw a polygon. draw_polygon_init() MUST be called prior to this function.
+ */
+static PyObject *
+draw_polygon_shape(PyObject *, PyObject * args)
+{
+    int shape_index = 0;
+    PyObject * brush_shadow;
+    PyObject * pen_shadow;
+    SHPObject * shape;
+    wxPoint* points;
+    wxPen * pen;
+    wxBrush * brush;
+    int num_points;
+    wxDC * dc;
+    PyObject * py_draw_info;
+    s_draw_info * draw_info;
+
+    if (!PyArg_ParseTuple(args, "O!iOO",
+			  &PyCObject_Type, &py_draw_info,
+			  &shape_index, &pen_shadow, &brush_shadow))
+	return NULL;
+
+    draw_info = (s_draw_info*)PyCObject_AsVoidPtr(py_draw_info);
+    
+    if (pen_shadow == Py_None)
+    {
+	pen = NULL;
+    }
+    else
+    {
+	if (!wxPyConvertSwigPtr( pen_shadow, (void**)&pen, wxT("wxPen")))
+	{
+	    PyErr_SetString(PyExc_TypeError,
+		       "fourth argument must be a wxPen instance or None");
+	    return NULL;
+	}
+    }
+
+    if (brush_shadow == Py_None)
+    {
+	brush = NULL;
+    }
+    else
+    {
+	if (!wxPyConvertSwigPtr( brush_shadow, (void**)&brush, wxT("wxBrush")))
+	{
+	    PyErr_SetString(PyExc_TypeError,
+			"fifth argument must be a wxBrush instance or None");
+	    return NULL;
+	}
+    }
+
+    shape = pyshapelib_api->SHPReadObject(draw_info->handle, shape_index);
+    if (!shape)
+	return PyErr_Format(PyExc_ValueError,
+			    "Can't get shape %d from shapefile", shape_index);
+    
+    num_points = shape->nVertices + shape->nParts - 1;
+    points = project_points(shape->nVertices, shape->nParts,
+			    shape->padfX, shape->padfY, shape->panPartStart,
+			    draw_info->forward, 
+                            draw_info->inverse, 
+                            draw_info->scalex, 
+                            draw_info->scaley, 
+                            draw_info->offx, 
+                            draw_info->offy);
+    dc = draw_info->dc;
+
+    // If the shape is a polygon and a non-transparent brush was given,
+    // fill the polygon
+    if (shape->nSHPType == SHPT_POLYGON
+	&& brush && brush != wxTRANSPARENT_BRUSH)
+    {
+	dc->SetPen(*wxTRANSPARENT_PEN);
+	dc->SetBrush(*brush);
+	dc->DrawPolygon(num_points, points, 0, 0);
+    }
+
+    // If a non-transparent pen was given, stroke the outline
+    if (pen && pen != wxTRANSPARENT_PEN)
+    {
+	draw_info->dc->SetPen(*pen);
+	draw_info->dc->SetBrush(*wxTRANSPARENT_BRUSH);
+	for (int i = 0; i < shape->nParts; i++)
+	{
+	    int length;
+
+	    if (i < shape->nParts - 1)
+		length = shape->panPartStart[i + 1] - shape->panPartStart[i];
+	    else
+		length = shape->nVertices - shape->panPartStart[i];
+
+	    // If the shape is a polygon, use DrawPolygon else use DrawLines
+	    if (shape->nSHPType == SHPT_POLYGON)
+	    {
+		dc->DrawPolygon(length, points + shape->panPartStart[i], 0, 0);
+	    }
+	    else
+	    {
+		dc->DrawLines(length, points + shape->panPartStart[i], 0, 0);
+	    }
+	}
+    }
+    
+    free(points);
+
+    pyshapelib_api->SHPDestroyObject(shape);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+
+
+/* determine whether the line fom (SX, SY) to (EX, EY) is `hit' by a
+ * click at (PX, PY), or whether a polygon containing this line is hit
+ * in the interior at (PX, PY).
+ *
+ * Return -1 if the line it self his hit. Otherwise, return +1 if a
+ * horizontal line from (PX, PY) to (-Infinity, PY) intersects the line
+ * and 0 if it doesn't.
+ *
+ * The nonnegative return values can be used to determine whether (PX, PY)
+ * is an interior point of a polygon according to the even-odd rule.
+ */
+
+#define PREC_BITS 4
+
+static int
+test_line(int sx, int sy, int ex, int ey, int px, int py)
+{
+    long vx, vy, dx, dy, len, dist, not_horizontal;
+
+    if (ey < sy)
+    {
+	dist = ex; ex = sx; sx = dist;
+	dist = ey; ey = sy; sy = dist;
+    }
+    not_horizontal = ey > sy + (2 << PREC_BITS);
+    if (not_horizontal && (py >= ey || py < sy))
+	return 0;
+
+    vx = ex - sx; vy = ey - sy;
+
+    len = (long)sqrt( (double) vx * vx + vy * vy);
+    if (!len)
+	/* degenerate case of coincident end points. Assumes that some
+	 * other part of the code has already determined whether the end
+	 * point is hit.
+	 */
+	return 0;
+
+    dx = px - sx; dy = py - sy;
+    dist = vx * dy - vy * dx;
+    if ((not_horizontal || (px >= sx && px <= ex) || (px >= ex && px <= sx))
+	&& abs(dist) <= (len << (PREC_BITS + 1)))
+	return -1;
+
+    /* horizontal lines (vy == 0) always return 0 here. */
+    return vy && py < ey && py >= sy && dx * abs(vy) > vx * abs(dy);
+}
+
+
+
+static PyObject *
+point_in_polygon_shape(PyObject *, PyObject * args)
+{
+    int shape_index = 0;
+    PyObject * shphandle_cobject;
+    PyObject * forward_cobject;
+    PyObject * inverse_cobject;
+    int filled, stroked;
+    double scalex, scaley, offx, offy;
+    int px, py;
+    SHPHandle handle;
+    projPJ * forward = NULL;
+    projPJ * inverse = NULL;
+    SHPObject * shape;
+    wxPoint* points;
+    int num_points;
+    int cross_count, linehit;
+    int result;
+
+    if (!PyArg_ParseTuple(args, "O!iiiOOddddii",
+			  &PyCObject_Type, &shphandle_cobject,
+			  &shape_index, &filled, &stroked,
+			  &forward_cobject, &inverse_cobject,
+			  &scalex, &scaley, &offx, &offy, &px, &py))
+	return NULL;
+
+    handle = (SHPHandle)PyCObject_AsVoidPtr(shphandle_cobject);
+
+    if (!extract_pointer(forward_cobject, &forward))
+	return NULL;
+
+    if (!extract_pointer(inverse_cobject, &inverse))
+	return NULL;
+
+    shape = pyshapelib_api->SHPReadObject(handle, shape_index);
+    if (!shape)
+	return PyErr_Format(PyExc_ValueError,
+			    "Can't get shape %d from shapefile", shape_index);
+
+    num_points = shape->nVertices + shape->nParts - 1;
+    points = project_points(shape->nVertices, shape->nParts,
+			    shape->padfX, shape->padfY, shape->panPartStart,
+			    forward, inverse, scalex, scaley, offx, offy);
+
+    long scaled_px = (px << PREC_BITS) + 1, scaled_py = (py << PREC_BITS) + 1;
+
+    cross_count = 0; linehit = 0;
+    for (int part = 0; part < shape->nParts; part++)
+    {
+	int start, end;
+
+	if (part < shape->nParts - 1)
+	{
+	    start = shape->panPartStart[part];
+	    end = shape->panPartStart[part + 1] - 1;
+	}
+	else
+	{
+	    start = shape->panPartStart[part];
+	    end = shape->nVertices - 1;
+	}
+
+	for (int vertex = start; vertex < end; vertex++)
+	{
+	    //printf("test_line: %d, %d: %d, %d -- %d, %d",
+	    //	   px, py, points[vertex].x, points[vertex].y,
+	    //	   points[vertex + 1].x, points[vertex + 1].y);
+	    result = test_line(points[vertex].x << PREC_BITS,
+				points[vertex].y << PREC_BITS,
+				points[vertex + 1].x << PREC_BITS,
+				points[vertex + 1].y << PREC_BITS,
+				scaled_px, scaled_py);
+	    //printf(":\t%d\n", result);
+	    if (result < 0)
+	    {
+		linehit = 1;
+		break;
+	    }
+	    cross_count += result;
+	}
+	if (linehit)
+	    break;
+    }
+
+    free(points);
+
+    pyshapelib_api->SHPDestroyObject(shape);
+
+    if (filled)
+    {
+	if (stroked && linehit)
+	    result = -1;
+	else
+	    result = cross_count % 2;
+    }
+    else if (stroked)
+    {
+	if (linehit)
+	    result = -1;
+	else
+	    result = 0;
+    }
+    else
+	result = 0;
+		
+
+    return PyInt_FromLong(result);
+}
+
+
+static PyObject*
+shape_centroid(PyObject *self, PyObject *args)
+{
+    int shape_index = 0;
+    PyObject * shphandle_cobject;
+    PyObject * forward_cobject;
+    PyObject * inverse_cobject;
+    double scalex, scaley, offx, offy;
+    SHPHandle handle;
+    projPJ * forward = NULL;
+    projPJ * inverse = NULL;
+    SHPObject * shape;
+    double centroidx = 0, centroidy = 0;
+    double sum = 0, area;
+    double lastx=0, lasty=0, x, y;
+
+    if (!PyArg_ParseTuple(args, "O!iOOdddd",
+			  &PyCObject_Type, &shphandle_cobject,
+			  &shape_index, &forward_cobject, &inverse_cobject,
+			  &scalex, &scaley, &offx, &offy))
+	return NULL;
+
+    handle = (SHPHandle)PyCObject_AsVoidPtr(shphandle_cobject);
+
+    if (!extract_pointer(forward_cobject, &forward))
+	return NULL;
+
+    if (!extract_pointer(inverse_cobject, &inverse))
+	return NULL;
+
+    shape = pyshapelib_api->SHPReadObject(handle, shape_index);
+    if (!shape)
+	return PyErr_Format(PyExc_ValueError,
+			    "Can't get shape %d from shapefile", shape_index);
+
+    for (int part = 0; part < shape->nParts; part++)
+    {
+	int start, end;
+
+	if (part < shape->nParts - 1)
+	{
+	    start = shape->panPartStart[part];
+	    end = shape->panPartStart[part + 1];
+	}
+	else
+	{
+	    start = shape->panPartStart[part];
+	    end = shape->nVertices;
+	}
+
+	project_point(&lastx, &lasty, forward, inverse,
+		      scalex, scaley, offx, offy,
+		      shape->padfX[start],
+		      shape->padfY[start]);
+	for (int vertex = start + 1; vertex < end; vertex++)
+	{
+	    project_point(&x, &y, forward, inverse,
+			  scalex, scaley, offx, offy,
+			  shape->padfX[vertex],
+			  shape->padfY[vertex]);
+	    area = x * lasty - lastx * y;
+	    centroidx += area * (x + lastx);
+	    centroidy += area * (y + lasty);
+	    sum += area;
+	    lastx = x;
+	    lasty = y;
+	}
+    }
+
+    pyshapelib_api->SHPDestroyObject(shape);
+
+    // Handle pathologic case where all points are equal.
+    if (sum == 0.0)
+    	return Py_BuildValue("dd", lastx, lasty);
+    else
+    	return Py_BuildValue("dd", centroidx / (3 * sum), centroidy / (3 * sum));
+}
+
+
+/*
+ * Returns a tuple containing the version of PROJ that was used when
+ * compiling this file (major, minor, release). If the version was
+ * not available (because of a very old version of PROJ) the tuple
+ * will be empty.
+ */
+
+static PyObject*
+get_proj_version(PyObject *, PyObject * args)
+{
+    PyObject * result;
+
+#ifdef PJ_VERSION
+    result = PyTuple_New(3);
+    if (result == NULL)
+        return NULL;
+
+    int ver = PJ_VERSION;
+    int major = ver / 100; ver -= major * 100;
+    int minor = ver / 10;  ver -= minor * 10;
+    int release = ver;
+
+    PyTuple_SET_ITEM(result, 0, PyInt_FromLong(major));
+    PyTuple_SET_ITEM(result, 1, PyInt_FromLong(minor));
+    PyTuple_SET_ITEM(result, 2, PyInt_FromLong(release));
+#else
+    result = PyTuple_New(0);
+    if (result == NULL)
+        return NULL;
+#endif
+
+    Py_INCREF(result);
+    return result;
+}
+
+
+static PyObject*
+get_gtk_version(PyObject *, PyObject * args)
+{
+    PyObject * result;
+
+#ifdef __WXGTK__
+    extern const int gtk_major_version;
+    extern const int gtk_minor_version;
+    extern const int gtk_micro_version;
+
+    result = PyTuple_New(3);
+    if (result == NULL)
+        return NULL;
+
+    PyTuple_SET_ITEM(result, 0, PyInt_FromLong(gtk_major_version));
+    PyTuple_SET_ITEM(result, 1, PyInt_FromLong(gtk_minor_version));
+    PyTuple_SET_ITEM(result, 2, PyInt_FromLong(gtk_micro_version));
+#else
+    result = PyTuple_New(0);
+    if (result == NULL)
+        return NULL;
+#endif
+
+    Py_INCREF(result);
+    return result;
+}
+
+
+/* Return the version of wxWindows this module was compiled with */
+static PyObject*
+get_wx_version(PyObject *, PyObject * args)
+{
+    return Py_BuildValue("iii", wxMAJOR_VERSION, wxMINOR_VERSION,
+			 wxRELEASE_NUMBER);
+}
+
+
+static PyMethodDef wxproj_methods[] = {
+    { "draw_polygon_shape", draw_polygon_shape, METH_VARARGS },
+    { "draw_polygon_init", draw_polygon_init, METH_VARARGS },
+    { "point_in_polygon_shape", point_in_polygon_shape, METH_VARARGS },
+    { "shape_centroid", shape_centroid, METH_VARARGS },
+    { "get_proj_version", get_proj_version, METH_VARARGS },
+    { "get_gtk_version", get_gtk_version, METH_VARARGS },
+    { "get_wx_version", get_wx_version, METH_VARARGS },
+    {NULL, NULL}
+};
+
+
+#ifdef __cplusplus
+extern "C" 
+#endif
+void initwxproj(void)
+{
+    PyObject * shapelib = NULL;
+    PyObject * c_api_func = NULL;
+    PyObject * cobj = NULL;
+
+    Py_InitModule("wxproj", wxproj_methods);
+
+    PYSHAPELIB_IMPORT_API(pyshapelib_api);
+
+    Py_XDECREF(cobj);
+    Py_XDECREF(c_api_func);
+    Py_XDECREF(shapelib);
+}
+
+
+

Added: packages/thuban/branches/upstream/current/po/Makefile
===================================================================
--- packages/thuban/branches/upstream/current/po/Makefile	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/po/Makefile	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,39 @@
+
+all:
+	@echo 'Usage:'
+	@echo '   make pot        create thuban.pot'
+	@echo '   make update-po  merge a new thuban.po with the *.po files'
+	@echo '   make mo         create the mo files'
+
+MO_DIR = ../Resources/Locale
+PO_DIR = po
+DOMAIN = thuban
+
+LIST_POTFILES = grep -l "_(\"" ../Thuban/*.py ../Thuban/*/*.py
+
+
+pot:
+	xgettext -k_ -o $(DOMAIN).pot `$(LIST_POTFILES)`
+
+update-po:
+	for po in *.po; do \
+		lingua=`basename $$po .po`; \
+	        mv $$lingua.po $$lingua.old.po; \
+		if msgmerge -o $$lingua.po $$lingua.old.po $(DOMAIN).pot; then\
+		    rm $$lingua.old.po; \
+		else \
+		    rm -f $$lingua.po; \
+		    mv $$lingua.old.po $$lingua.po; \
+		fi \
+	done
+
+
+mo:
+	for po in *.po; do\
+		lingua=`basename $$po .po`; \
+		install -d $(MO_DIR)/$$lingua/LC_MESSAGES/ ; \
+		echo -n $$po": "; \
+		msgfmt --statistics \
+			-o $(MO_DIR)/$$lingua/LC_MESSAGES/$(DOMAIN).mo $$po ;\
+	done
+

Added: packages/thuban/branches/upstream/current/po/README
===================================================================
--- packages/thuban/branches/upstream/current/po/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/po/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,35 @@
+
+Thuban Message Translations
+===========================
+
+Updating the message catalogs currently only works on unix-like systems
+and requires xgettext 0.11. (0.10.x may work for everything but it will
+at least produce a lot of warnings during "make pot" because it doesn't
+know about python syntax.)
+
+ - When the thuban sources were edited so that e.g. messages have been
+   changed or added, run
+
+     $ make pot
+
+   to update the thuban.pot file. You also need to do this after a fresh
+   CVS checkout to build thuban.pot
+
+ - When the thuban.pot file has been changed, run
+
+     $ make update-po
+
+   to merge the changes in the pot file with the messages already in the
+   .po files.
+
+ - When the translations in the po files have been changed, run
+
+     $ make mo
+
+   to generate new .mo files under ../Thuban/Resources/Locale
+
+ - The make mo command prints statistics about the translations.  To get
+   a less verbose version use this:
+
+     $ make mo 2>&1 | sed -e 's/ \(messages\|translations\)//g' -e 's/\.$//'
+

Added: packages/thuban/branches/upstream/current/po/de.po
===================================================================
--- packages/thuban/branches/upstream/current/po/de.po	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/po/de.po	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1837 @@
+# German Translation for Thuban.
+# Copyright (C) 2003 Bjoern Broscheit
+# Copyright (C) 2003, 2005 Intevation GmbH
+# This file is distributed under the same license as the Thuban package.
+# Bjoern Broscheit <bjoern at intevation.de>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Thuban 1.0.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-03-13 20:15+0000\n"
+"PO-Revision-Date: 2003-12-23 12:31+0100\n"
+"Last-Translator: Bernhard Herzog <bh at intevation.de>\n"
+"Language-Team: german <bjoern at intevation.de>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../Thuban/version.py:189
+#, python-format
+msgid "%s %s < %s"
+msgstr "%s %s < %s"
+
+#: ../Thuban/version.py:195
+#, python-format
+msgid "Thuban was compiled with wx %(wxproj-wx)s but wxPython is %(wxPython)s"
+msgstr ""
+"Thuban wurde für wxPython %(wxproj-wx)s gebaut aber wxPython hat die version "
+"%(wxPython)s"
+
+#: ../Thuban/Lib/connector.py:65
+#, python-format
+msgid "no receivers for channel %s of %s"
+msgstr "keine Empfänger für Kanal %s von %s"
+
+#: ../Thuban/Lib/connector.py:70
+#, python-format
+msgid "receiver %s%s is not connected to channel %s of %s"
+msgstr "Empfänger %s%s ist nicht verbunden mit Kanal %s von %s"
+
+#: ../Thuban/Lib/connector.py:94
+#, python-format
+msgid "Warning: %s.%s: %s%s\n"
+msgstr "Warnung: %s.%s: %s%s\n"
+
+#: ../Thuban/Lib/connector.py:118
+#, python-format
+msgid "\tmethod %s of %s"
+msgstr "\tmethod %s of %s"
+
+#: ../Thuban/Lib/fileutil.py:87 ../Thuban/Lib/fileutil.py:141
+msgid "first argument must be an absolute filename"
+msgstr "erstes Argument muss ein absoluter Dateiname sein"
+
+#: ../Thuban/Lib/fileutil.py:138
+msgid "Both parameters must have a drive letter"
+msgstr "Beide Parameter müssen einen Laufwerksbuchstaben haben"
+
+#: ../Thuban/Lib/fileutil.py:198
+msgid "No implementation of get_application_dir available for platform"
+msgstr ""
+"Keine Implementation von get_application_dir verfügbar für diese Plattform"
+
+#: ../Thuban/Lib/fileutil.py:208
+msgid "No implementation of relative_filename available for platform"
+msgstr ""
+"Keine Implementation von relative_filename verfügbar für diese Plattform"
+
+#: ../Thuban/Model/classgen.py:338
+msgid "invalid index"
+msgstr "Ungültiger Index"
+
+#: ../Thuban/Model/classification.py:309 ../Thuban/UI/classifier.py:758
+msgid "None"
+msgstr "Keine"
+
+#: ../Thuban/Model/classification.py:325
+msgid "Line Color"
+msgstr "Linienfarbe"
+
+#: ../Thuban/Model/classification.py:327
+#, python-format
+msgid "Line Width: %s"
+msgstr "Linienbreite: %s"
+
+#: ../Thuban/Model/classification.py:333
+#, python-format
+msgid "Size: %s"
+msgstr "Größe: %s"
+
+#: ../Thuban/Model/classification.py:336
+msgid "Fill"
+msgstr "Füllung"
+
+#: ../Thuban/Model/classification.py:342 ../Thuban/UI/classifier.py:841
+msgid "Classification"
+msgstr "Klassifikation"
+
+#: ../Thuban/Model/classification.py:436
+msgid "lineWidth < 1"
+msgstr "Linienbreite <1"
+
+#: ../Thuban/Model/classification.py:451
+msgid "size < 1"
+msgstr "size < 1"
+
+#: ../Thuban/Model/classification.py:656 ../Thuban/UI/classifier.py:528
+msgid "DEFAULT"
+msgstr "DEFAULT"
+
+#: ../Thuban/Model/data.py:316
+msgid "Table not compatible with shapestore."
+msgstr "Tabelle ist nicht kompatibel mit dem Format der Shapespeicherung."
+
+#: ../Thuban/Model/extension.py:90
+#, python-format
+msgid "Extension: %s"
+msgstr "Extension: %s"
+
+#: ../Thuban/Model/label.py:91
+#, python-format
+msgid "Number of labels: %d"
+msgstr "Anzahl der Labels: %d"
+
+#: ../Thuban/Model/label.py:92
+#, python-format
+msgid "Label Layer: %s"
+msgstr "Labelebene: %s"
+
+#: ../Thuban/Model/layer.py:298 ../Thuban/Model/layer.py:566
+#: ../Thuban/Model/session.py:432
+#, python-format
+msgid "Filename: %s"
+msgstr "Dateiname: %s"
+
+#: ../Thuban/Model/layer.py:301 ../Thuban/Model/layer.py:569
+msgid "Shown"
+msgstr "Sichtbar"
+
+#: ../Thuban/Model/layer.py:303 ../Thuban/Model/layer.py:571
+msgid "Hidden"
+msgstr "Unsichtbar"
+
+#: ../Thuban/Model/layer.py:304
+#, python-format
+msgid "Shapes: %d"
+msgstr "Shapes: %d"
+
+#: ../Thuban/Model/layer.py:308 ../Thuban/Model/layer.py:575
+#: ../Thuban/Model/map.py:287 ../Thuban/UI/rasterlayerproperties.py:51
+#, python-format
+msgid "Extent (lat-lon): (%g, %g, %g, %g)"
+msgstr "Ausdehnung (Breite-Länge): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/layer.py:310 ../Thuban/Model/layer.py:577
+msgid "Extent (lat-lon):"
+msgstr "Ausdehnung (Breite-Länge)"
+
+#: ../Thuban/Model/layer.py:311
+#, python-format
+msgid "Shapetype: %s"
+msgstr "Shapetyp: %s"
+
+#: ../Thuban/Model/layer.py:314 ../Thuban/Model/layer.py:580
+#: ../Thuban/Model/map.py:292
+msgid "Projection"
+msgstr "Projektion"
+
+#: ../Thuban/Model/layer.py:319 ../Thuban/Model/layer.py:583
+#, python-format
+msgid "Layer '%s'"
+msgstr "Ebene '%s'"
+
+#: ../Thuban/Model/load.py:78
+#, python-format
+msgid "Invalid hexadecimal color specification %s"
+msgstr "Ungültige hexadezimal Farbspezifikation %s"
+
+#: ../Thuban/Model/load.py:81
+#, python-format
+msgid "Invalid color specification %s"
+msgstr "Ungültige Farbspezifikation %s"
+
+#: ../Thuban/Model/load.py:544
+msgid "xml field type differs from database!"
+msgstr "XML-Feld-Typ unterscheidet sich von Datenbank!"
+
+#: ../Thuban/Model/load.py:609
+msgid "Classification range is not a number!"
+msgstr "Klassifikationswertebereich ist keine Zahl!"
+
+#: ../Thuban/Model/map.py:53
+msgid "Labels"
+msgstr "Labels"
+
+#: ../Thuban/Model/map.py:290
+#, python-format
+msgid "Extent (projected): (%g, %g, %g, %g)"
+msgstr "Ausdehnung (projiziert): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/map.py:301
+#, python-format
+msgid "Map: %s"
+msgstr "Karte: %s"
+
+#: ../Thuban/Model/proj.py:84 ../Thuban/Model/resource.py:179
+msgid "Unknown"
+msgstr "Unbekannt"
+
+#: ../Thuban/Model/resource.py:46
+#, python-format
+msgid ""
+"No GDAL support because module '%s' cannot be imported. Python exception: '%"
+"s'"
+msgstr ""
+"Keine GDAL Unterstützung weil das Modul '%s' nicht importiert werden kann. "
+"Python Fehler: '%s'"
+
+#: ../Thuban/Model/resource.py:135 ../Thuban/Model/resource.py:155
+#, python-format
+msgid "Could not read \"%s\": %s"
+msgstr "Konnte '%s' nicht lesen: %s"
+
+#: ../Thuban/Model/resource.py:187
+#, python-format
+msgid "Error in projection \"%s\": %s"
+msgstr "Fehler in Projection '%s': %s"
+
+#: ../Thuban/Model/save.py:352
+msgid "Unsupported group type in classification"
+msgstr "Nicht unterstützte Gruppentyp in Klassifikation"
+
+#: ../Thuban/Model/session.py:430
+msgid "Filename:"
+msgstr "Dateiname:"
+
+#: ../Thuban/Model/session.py:435
+msgid "Modified"
+msgstr "Geändert"
+
+#: ../Thuban/Model/session.py:437
+msgid "Unmodified"
+msgstr "Nicht geändert"
+
+#: ../Thuban/Model/session.py:442
+#, python-format
+msgid "Session: %s"
+msgstr "Session: %s"
+
+#: ../Thuban/Model/session.py:448
+msgid "unnamed session"
+msgstr "unbenannte Session"
+
+#: ../Thuban/Model/session.py:450
+msgid "unnamed map"
+msgstr "unbenannte Karte"
+
+#: ../Thuban/UI/about.py:28
+msgid "About Thuban"
+msgstr "Über Thuban"
+
+#: ../Thuban/UI/about.py:47
+msgid "French"
+msgstr "Französisch"
+
+#: ../Thuban/UI/about.py:48
+msgid "German"
+msgstr "Deutsch"
+
+#: ../Thuban/UI/about.py:50
+msgid "Hungarian"
+msgstr "Ungarisch"
+
+#: ../Thuban/UI/about.py:51
+msgid "Italian"
+msgstr "Italienisch"
+
+#: ../Thuban/UI/about.py:52
+msgid "Portuguese (Brazilian)"
+msgstr "Portugiesisch (Brasilianisch)"
+
+#: ../Thuban/UI/about.py:53
+msgid "Russian"
+msgstr "Russisch"
+
+#: ../Thuban/UI/about.py:54
+msgid "Spanish"
+msgstr "Spanish"
+
+#: ../Thuban/UI/about.py:63 ../Thuban/UI/about.py:65 ../Thuban/UI/about.py:67
+msgid "- not available"
+msgstr "- nicht verfügbar"
+
+#: ../Thuban/UI/about.py:72
+msgid "Currently using:\n"
+msgstr "Aktuell verwendet:\n"
+
+#: ../Thuban/UI/about.py:78
+#, python-format
+msgid "\tInternal encoding: %s\n"
+msgstr "\tInterne Zeichencodierung: %s\n"
+
+#: ../Thuban/UI/about.py:84
+msgid "Compiled for:\n"
+msgstr "Übersetzt für:\n"
+
+#: ../Thuban/UI/about.py:90
+msgid "Extensions:\n"
+msgstr "Extensions:\n"
+
+#: ../Thuban/UI/about.py:95 ../Thuban/UI/about.py:144
+msgid "\tNone registered.\n"
+msgstr "\tKeine registriert.\n"
+
+#: ../Thuban/UI/about.py:98
+msgid "Maintainers:\n"
+msgstr "Verwalter:\n"
+
+#: ../Thuban/UI/about.py:103
+msgid "Lead Developer:\n"
+msgstr "Hauptentwickler:\n"
+
+#: ../Thuban/UI/about.py:106
+msgid "Developers:\n"
+msgstr "Entwickler:\n"
+
+#: ../Thuban/UI/about.py:111
+msgid "Translators:\n"
+msgstr "Übersetzer:\n"
+
+#: ../Thuban/UI/about.py:116
+msgid "Other Contributors:\n"
+msgstr "Weitere Mitwirkende:\n"
+
+#: ../Thuban/UI/about.py:122
+msgid ""
+"Questions and comments can be sent to the following addresses:\n"
+"\tGeneral list (public):\n"
+"\t\t<thuban-list at intevation.de>\n"
+"\tDevelopers list (public):\n"
+"\t\t<thuban-devel at intevation.de>\n"
+"\tThuban team at Intevation:\n"
+"\t\t<thuban at intevation.de>\n"
+msgstr ""
+"Fragen und Kommentare können an die folgenden Adressen geschickt werden:\n"
+"\tThuban Entwickler:\n"
+"\t\t<thuban at intevation.de>\n"
+"\tThuban Mailingliste:\n"
+"\t\t<thuban-list at intevation.de>\n"
+"        Thuban team at Intevation:\n"
+"                <thuban at intevation.de>\n"
+
+#: ../Thuban/UI/about.py:130
+msgid ""
+"Details on the registered extensions:\n"
+"\n"
+msgstr ""
+"Details zu den registrierten Extensions:\n"
+"\n"
+
+#: ../Thuban/UI/about.py:135
+#, python-format
+msgid "Copyright %s\n"
+msgstr "Copyright %s\n"
+
+#: ../Thuban/UI/about.py:136
+msgid "Authors:\n"
+msgstr "Autoren:\n"
+
+#: ../Thuban/UI/about.py:149
+msgid ""
+"Thuban is a program for exploring geographic data.\n"
+"\n"
+msgstr ""
+"Thuban ist ein Programm zur Erkundung von Geografischen Daten\n"
+"\n"
+
+#: ../Thuban/UI/about.py:151
+msgid "Thuban is licensed under the GNU GPL"
+msgstr "Thuban ist lizenziert unter der GNU GPL"
+
+#: ../Thuban/UI/about.py:160 ../Thuban/UI/classgen.py:91
+#: ../Thuban/UI/dbdialog.py:276 ../Thuban/UI/dock.py:371
+#: ../Thuban/UI/join.py:66 ../Thuban/UI/layerproperties.py:82
+#: ../Thuban/UI/projdialog.py:209 ../Thuban/UI/tableview.py:388
+msgid "Close"
+msgstr "Schließen"
+
+#: ../Thuban/UI/altpathdialog.py:24
+#, python-format
+msgid "Select an alternative data file for %s"
+msgstr "Wählen Sie eine andere Datei für %s"
+
+#: ../Thuban/UI/altpathdialog.py:31 ../Thuban/UI/mainwindow.py:563
+msgid "Shapefiles (*.shp)"
+msgstr "Shapefiles (*.shp)"
+
+#: ../Thuban/UI/altpathdialog.py:32 ../Thuban/UI/mainwindow.py:564
+#: ../Thuban/UI/mainwindow.py:852
+msgid "All Files (*.*)"
+msgstr "Alle Dateien (*.*)"
+
+#: ../Thuban/UI/altpathdialog.py:47
+#, python-format
+msgid ""
+"Found the following as an alternative for %s.\n"
+"%s\n"
+"\n"
+" Please confirm with Yes or select alternative with No."
+msgstr ""
+"Habe die folgende Alternative für %s gefunden.\n"
+"%s\n"
+"\n"
+"Bitte bestätigen Sie mit Ja oder wählen Sie eine andere mit Nein"
+
+#: ../Thuban/UI/altpathdialog.py:49
+msgid "Alternative Path"
+msgstr "Alternativer Dateiname"
+
+#: ../Thuban/UI/application.py:110 ../Thuban/UI/application.py:122
+msgid "Cannot import the thubanstart module\n"
+msgstr "Thubanstartmodule können nicht importiert werden\n"
+
+#: ../Thuban/UI/application.py:115
+msgid "No thubanstart module available\n"
+msgstr "Thubanstartmodul nicht verfügbar\n"
+
+#: ../Thuban/UI/application.py:126
+msgid "No ~/.thuban directory\n"
+msgstr "~/.thuban Verzeichnis nicht vorhanden\n"
+
+#: ../Thuban/UI/application.py:166
+msgid ""
+"This is the wxPython-based Graphical User Interface for exploring geographic "
+"data"
+msgstr ""
+"Ein wxPython basiertes Grafisches Benutzerinterface für das Erkunden von "
+"Geografischen Daten"
+
+#: ../Thuban/UI/application.py:254
+msgid ""
+"The current session contains Image layers,\n"
+"but the GDAL library is not available to draw them."
+msgstr ""
+"Die aktuelle Session beinhaltet Bildebenen,\n"
+"jedoch die GDAL Bibliothek ist nicht verfügbarum diese darzustellen."
+
+#: ../Thuban/UI/application.py:259
+msgid "Library not available"
+msgstr "Bibliothek nicht verfügbar"
+
+#: ../Thuban/UI/application.py:268 ../Thuban/UI/mainwindow.py:476
+msgid "DB Connection Parameters"
+msgstr "DB Verbindungsparameter"
+
+#: ../Thuban/UI/application.py:364
+#, python-format
+msgid ""
+"An unhandled exception occurred:\n"
+"%s\n"
+"(please report to http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+msgstr ""
+"Eine unbehandelte Ausnahme ist aufgetreten:\n"
+"%s\n"
+"(please report to http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/classgen.py:43
+msgid "Uniform Distribution"
+msgstr "Gleichförmige Verteilung"
+
+#: ../Thuban/UI/classgen.py:44
+msgid "Unique Values"
+msgstr "Eindeutige Werte"
+
+#: ../Thuban/UI/classgen.py:45
+msgid "Quantiles from Table"
+msgstr "Quantile aus Tabelle"
+
+#: ../Thuban/UI/classgen.py:47
+msgid "Custom Ramp"
+msgstr "Benutzerdefinierter Verlauf"
+
+#: ../Thuban/UI/classgen.py:48
+msgid "Grey Ramp"
+msgstr "Grauer Verlauf"
+
+#: ../Thuban/UI/classgen.py:49
+msgid "Red Ramp"
+msgstr "Roter Verlauf"
+
+#: ../Thuban/UI/classgen.py:50
+msgid "Green Ramp"
+msgstr "Grüner Verlauf"
+
+#: ../Thuban/UI/classgen.py:51
+msgid "Blue Ramp"
+msgstr "Blauer Verlauf"
+
+#: ../Thuban/UI/classgen.py:52
+msgid "Green-to-Red Ramp"
+msgstr "Grün-nach-Rot Verlauf"
+
+#: ../Thuban/UI/classgen.py:53
+msgid "Hot-to-Cold Ramp"
+msgstr "Heiß-nach-Kalt Verlauf"
+
+#: ../Thuban/UI/classgen.py:69
+msgid "Generate Classification"
+msgstr "Erzeuge Klassifikation"
+
+#: ../Thuban/UI/classgen.py:90
+msgid "Generate"
+msgstr "Erzeuge"
+
+#: ../Thuban/UI/classgen.py:119
+#, python-format
+msgid "Field: %s"
+msgstr "Feld: %s"
+
+#: ../Thuban/UI/classgen.py:123 ../Thuban/UI/classifier.py:976
+#, python-format
+msgid "Data Type: %s"
+msgstr "Datentyp: %s"
+
+#: ../Thuban/UI/classgen.py:127
+msgid "Generate:"
+msgstr "Erzeuge:"
+
+#: ../Thuban/UI/classgen.py:137
+msgid "Color Scheme:"
+msgstr "Farbschema:"
+
+#: ../Thuban/UI/classgen.py:161
+msgid "Fix Border Color"
+msgstr "Rahmenfarbe festlegen"
+
+#: ../Thuban/UI/classgen.py:168 ../Thuban/UI/classgen.py:936
+#: ../Thuban/UI/classgen.py:967
+msgid "Change"
+msgstr "Ändern"
+
+#: ../Thuban/UI/classgen.py:274
+msgid ""
+"Based on the data from the table and the input\n"
+"values, the exact quantiles could not be generated.\n"
+"\n"
+"Accept a close estimate?"
+msgstr ""
+"Basiert auf die Daten aus der Tabelle und der\n"
+"Eingabewerte, können die exakten Quantile nicht erzeugt werden.\n"
+"\n"
+"Akzeptieren der geschätzten Näherung?"
+
+#: ../Thuban/UI/classgen.py:277
+msgid "Problem with Quantiles"
+msgstr "Probleme mit Quantile"
+
+#: ../Thuban/UI/classgen.py:370
+msgid "Min:"
+msgstr "Min:"
+
+#: ../Thuban/UI/classgen.py:375
+msgid "Max:"
+msgstr "Max:"
+
+#: ../Thuban/UI/classgen.py:380 ../Thuban/UI/classgen.py:633
+msgid "Retrieve From Table"
+msgstr "Aus Tabelle holen"
+
+#: ../Thuban/UI/classgen.py:390
+msgid "Number of Groups:"
+msgstr "Anzahl der Gruppen:"
+
+#: ../Thuban/UI/classgen.py:397
+msgid "Stepping:"
+msgstr "Stufen:"
+
+#: ../Thuban/UI/classgen.py:647
+msgid "Available"
+msgstr "Verfügbar"
+
+#: ../Thuban/UI/classgen.py:652 ../Thuban/UI/classgen.py:692
+msgid "Sort"
+msgstr "Sortieren"
+
+#: ../Thuban/UI/classgen.py:655 ../Thuban/UI/classgen.py:695
+msgid "Reverse"
+msgstr "Umkehren"
+
+#: ../Thuban/UI/classgen.py:687
+msgid "Use"
+msgstr "Verwenden"
+
+#: ../Thuban/UI/classgen.py:832
+msgid "Retrieve from Table"
+msgstr "Aus Tabelle holen"
+
+#: ../Thuban/UI/classgen.py:840
+msgid "Apply to Range"
+msgstr "Anwenden auf Wertebereich"
+
+#: ../Thuban/UI/classgen.py:847
+msgid "Number of Classes:"
+msgstr "Anzahl der Klassen:"
+
+#: ../Thuban/UI/classgen.py:930
+msgid "Start:"
+msgstr "Start:"
+
+#: ../Thuban/UI/classgen.py:961
+msgid "End:"
+msgstr "Ende:"
+
+#: ../Thuban/UI/classifier.py:164
+msgid "The Default group cannot be removed."
+msgstr "Die Defaultgruppe kann nicht entfernt werden."
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:309
+#: ../Thuban/UI/classifier.py:467
+msgid "Pattern"
+msgstr "Muster"
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:306
+#: ../Thuban/UI/classifier.py:466
+msgid "Singleton"
+msgstr "Singleton"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Visible"
+msgstr "Sichtbar"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Symbol"
+msgstr "Symbol"
+
+#: ../Thuban/UI/classifier.py:317 ../Thuban/UI/controls.py:33
+#: ../Thuban/UI/controls.py:177
+msgid "Value"
+msgstr "Wert"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Label"
+msgstr "Label"
+
+#: ../Thuban/UI/classifier.py:462 ../Thuban/UI/classifier.py:465
+msgid "Default"
+msgstr "Default"
+
+#: ../Thuban/UI/classifier.py:468
+msgid "Range"
+msgstr "Wertebereich"
+
+#: ../Thuban/UI/classifier.py:469
+msgid "Map"
+msgstr "Karte"
+
+#: ../Thuban/UI/classifier.py:759
+msgid "Text"
+msgstr "Text"
+
+#: ../Thuban/UI/classifier.py:760
+msgid "Integer"
+msgstr "Integer"
+
+#: ../Thuban/UI/classifier.py:761
+msgid "Decimal"
+msgstr "Dezimal"
+
+#: ../Thuban/UI/classifier.py:820
+msgid "Generate Class"
+msgstr "Erzeuge Klasse"
+
+#: ../Thuban/UI/classifier.py:822 ../Thuban/UI/dbdialog.py:274
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: ../Thuban/UI/classifier.py:824
+msgid "Move Up"
+msgstr "Eine Ebene nach oben bewegen"
+
+#: ../Thuban/UI/classifier.py:826
+msgid "Move Down"
+msgstr "Eine Ebene nach unten bewegen"
+
+#: ../Thuban/UI/classifier.py:828
+msgid "Edit Symbol"
+msgstr "Symbol bearbeiten"
+
+#: ../Thuban/UI/classifier.py:830 ../Thuban/UI/dbdialog.py:275
+#: ../Thuban/UI/projdialog.py:117
+msgid "Remove"
+msgstr "Entfernen"
+
+#: ../Thuban/UI/classifier.py:845
+msgid "Field: "
+msgstr "Feld:"
+
+#: ../Thuban/UI/classifier.py:1000 ../Thuban/UI/layerproperties.py:160
+msgid "Layer Properties"
+msgstr "Ebenen Einstellungen"
+
+#: ../Thuban/UI/classifier.py:1167
+msgid "Select Properties"
+msgstr "Ausgewählte Eigenschaften"
+
+#: ../Thuban/UI/classifier.py:1178
+msgid "Preview:"
+msgstr "Vorschau:"
+
+#: ../Thuban/UI/classifier.py:1195
+msgid "Change Line Color"
+msgstr "Linienfarbe ändern"
+
+#: ../Thuban/UI/classifier.py:1201 ../Thuban/UI/classifier.py:1216
+msgid "Transparent"
+msgstr "Transparenz"
+
+#: ../Thuban/UI/classifier.py:1212
+msgid "Change Fill Color"
+msgstr "Füllfarbe ändern"
+
+#: ../Thuban/UI/classifier.py:1225
+msgid "Line Width: "
+msgstr "Linienbreite:"
+
+#: ../Thuban/UI/classifier.py:1242
+msgid "Size: "
+msgstr "Größe: "
+
+#: ../Thuban/UI/classifier.py:1262 ../Thuban/UI/colordialog.py:52
+#: ../Thuban/UI/dbdialog.py:107 ../Thuban/UI/dbdialog.py:221
+#: ../Thuban/UI/labeldialog.py:41 ../Thuban/UI/layerproperties.py:81
+#: ../Thuban/UI/projdialog.py:205
+msgid "OK"
+msgstr "OK"
+
+#: ../Thuban/UI/classifier.py:1264 ../Thuban/UI/colordialog.py:53
+#: ../Thuban/UI/dbdialog.py:110 ../Thuban/UI/dbdialog.py:223
+#: ../Thuban/UI/labeldialog.py:42 ../Thuban/UI/projdialog.py:1033
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: ../Thuban/UI/colordialog.py:39
+msgid "Select Color"
+msgstr "Farbe Auswählen"
+
+#: ../Thuban/UI/controls.py:31
+msgid "Field"
+msgstr "Feld"
+
+#: ../Thuban/UI/dbdialog.py:41
+msgid "Choose layer from database"
+msgstr "Ebene aus Datenbank wählen"
+
+#: ../Thuban/UI/dbdialog.py:59
+msgid "Databases"
+msgstr "Datenbanken"
+
+#: ../Thuban/UI/dbdialog.py:74
+msgid "Retrieve"
+msgstr "Holen"
+
+#: ../Thuban/UI/dbdialog.py:82
+msgid "Tables"
+msgstr "Tabellen"
+
+#: ../Thuban/UI/dbdialog.py:92
+msgid "ID Column"
+msgstr "ID-Spalte"
+
+#: ../Thuban/UI/dbdialog.py:98
+msgid "Geometry Column"
+msgstr "Geometriespalte"
+
+#: ../Thuban/UI/dbdialog.py:187
+msgid "Hostname:"
+msgstr "Rechnername:"
+
+#: ../Thuban/UI/dbdialog.py:191
+msgid "Port:"
+msgstr "Port:"
+
+#: ../Thuban/UI/dbdialog.py:198
+msgid "Database Name:"
+msgstr "Datenbankname:"
+
+#: ../Thuban/UI/dbdialog.py:206
+msgid "User:"
+msgstr "Benutzer:"
+
+#: ../Thuban/UI/dbdialog.py:211
+msgid "Password:"
+msgstr "Passwort:"
+
+#: ../Thuban/UI/dbdialog.py:286
+msgid "Database Management"
+msgstr "Datenbank Verwaltung"
+
+#: ../Thuban/UI/dbdialog.py:361 ../Thuban/UI/dbdialog.py:366
+msgid "Add Database"
+msgstr "Datenbank Hinzufügen"
+
+#: ../Thuban/UI/dbdialog.py:367
+#, python-format
+msgid "Connection '%s' already exists"
+msgstr "Verbindung '%s' existiert bereits"
+
+#: ../Thuban/UI/dbdialog.py:388
+msgid "Remove Database Connection"
+msgstr "Datenbankverbindung entfernen"
+
+#: ../Thuban/UI/dbdialog.py:389
+#, python-format
+msgid ""
+"The connection %s\n"
+"is still in use"
+msgstr ""
+"Die Verbindung %s\n"
+"wird noch verwendet"
+
+#: ../Thuban/UI/dock.py:190
+msgid "Undock"
+msgstr "Undock"
+
+#: ../Thuban/UI/dock.py:218
+msgid "Dock"
+msgstr "Dock"
+
+#: ../Thuban/UI/exceptiondialog.py:23 ../Thuban/UI/exceptiondialog.py:61
+msgid "Thuban: Internal Error"
+msgstr "Thuban: Interner Fehler"
+
+#: ../Thuban/UI/exceptiondialog.py:43
+msgid "Proceed"
+msgstr "Fortfahren"
+
+#: ../Thuban/UI/exceptiondialog.py:44
+msgid "Exit Thuban now"
+msgstr "Thuban jetzt beenden"
+
+#: ../Thuban/UI/extensionregistry.py:72
+msgid "Initialization not yet requested."
+msgstr "Initialisierung noch nicht angefordert."
+
+#: ../Thuban/UI/extensionregistry.py:88
+msgid "Initialization successful."
+msgstr "Initialisierung erfolgreicht."
+
+#: ../Thuban/UI/identifyview.py:44
+msgid "Identify Shape"
+msgstr "Shape identifizieren"
+
+#: ../Thuban/UI/identifyview.py:56
+msgid "Close Window"
+msgstr "Fenster Schließen"
+
+#: ../Thuban/UI/identifyview.py:57
+msgid "Stop Identify Mode"
+msgstr "Identifizierung Stoppen"
+
+#: ../Thuban/UI/join.py:64
+msgid "Join"
+msgstr "Verbinden"
+
+#: ../Thuban/UI/join.py:71 ../Thuban/UI/join.py:72
+msgid "Select..."
+msgstr "Auswählen..."
+
+#: ../Thuban/UI/join.py:100 ../Thuban/UI/join.py:108
+msgid "Table:"
+msgstr "Tabelle:"
+
+#: ../Thuban/UI/join.py:111 ../Thuban/UI/join.py:114
+msgid "Field:"
+msgstr "Feld:"
+
+#: ../Thuban/UI/join.py:125
+msgid "Outer Join (preserves left table records)"
+msgstr "Äussere Verbindung (Erhält den linken Tabelleneintrag)"
+
+#: ../Thuban/UI/join.py:173
+#, python-format
+msgid ""
+"Join failed:\n"
+"  %s"
+msgstr ""
+"Verbinden schlug fehl:\n"
+" %s"
+
+#: ../Thuban/UI/join.py:174
+msgid "Info"
+msgstr "Info"
+
+#: ../Thuban/UI/join.py:195
+#, python-format
+msgid ""
+"The joined table has %(joined)d rows but it must have %(needed)d rows to be "
+"used with the selected layer"
+msgstr ""
+"Die verbundene Tabelle hat %(joined)d Zeilen aber diese muss %(needed)d "
+"Zeilen haben, um mit der ausgewählten Ebene verwendet werden zu können"
+
+#: ../Thuban/UI/join.py:200
+msgid "Join Failed"
+msgstr "Verbinden schlug fehl"
+
+#: ../Thuban/UI/join.py:209 ../Thuban/UI/mainwindow.py:915
+#, python-format
+msgid "Table: %s"
+msgstr "Tabelle: %s"
+
+#: ../Thuban/UI/labeldialog.py:26
+msgid "Label Values"
+msgstr "Labelwerte"
+
+#: ../Thuban/UI/layerproperties.py:54
+msgid "Title: "
+msgstr "Titel:"
+
+#: ../Thuban/UI/layerproperties.py:65
+#, python-format
+msgid "Layer Type: %s"
+msgstr "Ebenentyp: %s"
+
+#: ../Thuban/UI/layerproperties.py:71
+msgid "Projection: None"
+msgstr "Projektion: Keine"
+
+#: ../Thuban/UI/layerproperties.py:73
+#, python-format
+msgid "Projection: %s"
+msgstr "Projektion: %s"
+
+#: ../Thuban/UI/layerproperties.py:79 ../Thuban/UI/projdialog.py:199
+msgid "Try"
+msgstr "Anwenden"
+
+#: ../Thuban/UI/layerproperties.py:80 ../Thuban/UI/projdialog.py:202
+msgid "Revert"
+msgstr "Zurücksetzen"
+
+#: ../Thuban/UI/legend.py:75
+msgid "Top Layer"
+msgstr "Auf die oberste Ebene bewegen"
+
+#: ../Thuban/UI/legend.py:79
+msgid "Raise Layer"
+msgstr "Eine Ebene nach oben bewegen"
+
+#: ../Thuban/UI/legend.py:83
+msgid "Lower Layer"
+msgstr "Eine Ebene nach unten bewegen"
+
+#: ../Thuban/UI/legend.py:87
+msgid "Bottom Layer"
+msgstr "Auf die unterste Ebene bewegen"
+
+#: ../Thuban/UI/legend.py:91
+msgid "Show Layer"
+msgstr "Sichtbar"
+
+#: ../Thuban/UI/legend.py:95
+msgid "Hide Layer"
+msgstr "Nicht sichtbar"
+
+#: ../Thuban/UI/legend.py:99
+msgid "Edit Layer Properties"
+msgstr "Ebeneneinstellungen bearbeiten"
+
+#: ../Thuban/UI/mainwindow.py:264 ../Thuban/UI/mainwindow.py:286
+#, python-format
+msgid "Unknown command %s"
+msgstr "Unbekanntes Kommando %s"
+
+#: ../Thuban/UI/mainwindow.py:299
+#, python-format
+msgid "Unknown command ID %d"
+msgstr "Unbekannte Kommando ID %d"
+
+#: ../Thuban/UI/mainwindow.py:338
+#, python-format
+msgid "The Dialog named %s is already open"
+msgstr "Der Dialog %s ist bereits geöffnet"
+
+#: ../Thuban/UI/mainwindow.py:396
+#, python-format
+msgid "Select layer '%s' and pick a projection using Layer/Projection..."
+msgstr ""
+"Wählen Sie die Ebene '%s' und wählen eine Projektion mit Ebene/Projektion..."
+
+#: ../Thuban/UI/mainwindow.py:449
+msgid "Exit"
+msgstr "Beenden"
+
+#: ../Thuban/UI/mainwindow.py:450
+msgid "The session has been modified. Do you want to save it?"
+msgstr "Die Session wurde geändert! Möchten Sie diese speichern?"
+
+#: ../Thuban/UI/mainwindow.py:465
+msgid "Open Session"
+msgstr "Öffne Session"
+
+#: ../Thuban/UI/mainwindow.py:487
+msgid "Save Session As"
+msgstr "Speichere Session unter ..."
+
+#: ../Thuban/UI/mainwindow.py:561
+msgid "Select one or more data files"
+msgstr "Eine oder mehrere Dateien auswählen"
+
+#: ../Thuban/UI/mainwindow.py:576
+msgid "Add Layer"
+msgstr "Ebene hinzufügen"
+
+#: ../Thuban/UI/mainwindow.py:577 ../Thuban/UI/mainwindow.py:602
+#: ../Thuban/UI/mainwindow.py:862
+#, python-format
+msgid "Can't open the file '%s'."
+msgstr "Kann Datei nicht öffnen  '%s'."
+
+#: ../Thuban/UI/mainwindow.py:589
+msgid "Select an image file"
+msgstr "Bilddatei wählen"
+
+#: ../Thuban/UI/mainwindow.py:601
+msgid "Add Image Layer"
+msgstr "Bildebene hinzufügen"
+
+#: ../Thuban/UI/mainwindow.py:629
+msgid "Add Layer from database"
+msgstr "Ebene aus Datenbank hinzufügen"
+
+#: ../Thuban/UI/mainwindow.py:630
+#, python-format
+msgid "Can't open the database table '%s'"
+msgstr "Kann Datenbanktabelle '%s' nicht öffnen."
+
+#: ../Thuban/UI/mainwindow.py:719
+#, python-format
+msgid "Copy of `%s'"
+msgstr "Kopie von  `%s'"
+
+#: ../Thuban/UI/mainwindow.py:749
+#, python-format
+msgid "Layer Table: %s"
+msgstr "Ebenentabelle: %s"
+
+#: ../Thuban/UI/mainwindow.py:764
+#, python-format
+msgid "Map Projection: %s"
+msgstr "Kartenprojektion: %s"
+
+#: ../Thuban/UI/mainwindow.py:779
+#, python-format
+msgid "Layer Projection: %s"
+msgstr "Ebenenprojektion: %s"
+
+#: ../Thuban/UI/mainwindow.py:812
+msgid "Join Layer with Table"
+msgstr "Verbinde Ebene mit Tabelle"
+
+#: ../Thuban/UI/mainwindow.py:834 ../Thuban/UI/mainwindow.py:1165
+msgid "Legend"
+msgstr "Legende"
+
+#: ../Thuban/UI/mainwindow.py:848 ../Thuban/UI/mainwindow.py:861
+msgid "Open Table"
+msgstr "Öffne Tabelle"
+
+#: ../Thuban/UI/mainwindow.py:850
+msgid "DBF Files (*.dbf)"
+msgstr "DBF Dateien (*.dbf)"
+
+#: ../Thuban/UI/mainwindow.py:873
+msgid "Pick the tables to close:"
+msgstr "Wähle die Tabellen zum Schließen:"
+
+#: ../Thuban/UI/mainwindow.py:874
+msgid "Close Table"
+msgstr "Tabelle schließen"
+
+#: ../Thuban/UI/mainwindow.py:894
+msgid "Pick the table to show:"
+msgstr "Wähle Tabellen zum Anzeigen:"
+
+#: ../Thuban/UI/mainwindow.py:895
+msgid "Show Table"
+msgstr "Tabelle anzeigen"
+
+#: ../Thuban/UI/mainwindow.py:906
+msgid "Join Tables"
+msgstr "Tabellen verbinden"
+
+#: ../Thuban/UI/mainwindow.py:929
+msgid "Pick the table to rename:"
+msgstr "Wähle Tabellen zum Umbenennen:"
+
+#: ../Thuban/UI/mainwindow.py:930 ../Thuban/UI/mainwindow.py:942
+msgid "Rename Table"
+msgstr "Tabelle umbenennen"
+
+#: ../Thuban/UI/mainwindow.py:942
+msgid "Table Title:"
+msgstr "Tabellentitel:"
+
+#: ../Thuban/UI/mainwindow.py:991
+msgid "Map Title:"
+msgstr "Kartentitel:"
+
+#: ../Thuban/UI/mainwindow.py:991
+msgid "Rename Map"
+msgstr "Karte Umbenennen"
+
+#: ../Thuban/UI/mainwindow.py:1004
+msgid "Layer Title:"
+msgstr "Ebenentitel: %s"
+
+#: ../Thuban/UI/mainwindow.py:1004
+msgid "Rename Layer"
+msgstr "Ebene Umbenennen"
+
+#: ../Thuban/UI/mainwindow.py:1057
+#, python-format
+msgid "Thuban - %s"
+msgstr "Thuban - %s"
+
+#: ../Thuban/UI/mainwindow.py:1059
+msgid "Thuban"
+msgstr "Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1154
+msgid "&New Session"
+msgstr "&Neue Session"
+
+#: ../Thuban/UI/mainwindow.py:1155
+msgid "Start a new session"
+msgstr "Starte eine neue Session"
+
+#: ../Thuban/UI/mainwindow.py:1156
+msgid "&Open Session..."
+msgstr "&Öffne Session"
+
+#: ../Thuban/UI/mainwindow.py:1157
+msgid "Open a session file"
+msgstr "Sessiondatei öffnen"
+
+#: ../Thuban/UI/mainwindow.py:1158
+msgid "&Save Session"
+msgstr "&Speichere Session"
+
+#: ../Thuban/UI/mainwindow.py:1159
+msgid "Save this session to the file it was opened from"
+msgstr "Speichere diese Session in die Datei, die geöffnet wurde von"
+
+#: ../Thuban/UI/mainwindow.py:1160
+msgid "Save Session &As..."
+msgstr "Speichere Session &Unter..."
+
+#: ../Thuban/UI/mainwindow.py:1161
+msgid "Save this session to a new file"
+msgstr "Diese Session in einer neuen Datei speichern"
+
+#: ../Thuban/UI/mainwindow.py:1162
+msgid "Session &Tree"
+msgstr "Session &Baum"
+
+#: ../Thuban/UI/mainwindow.py:1164
+msgid "Toggle on/off the session tree analysis window"
+msgstr "Das Analysefenster des Sessionbaums zeigen/schließen"
+
+#: ../Thuban/UI/mainwindow.py:1167
+msgid "Toggle Legend on/off"
+msgstr "Legende zeigen/schließen"
+
+#: ../Thuban/UI/mainwindow.py:1168
+msgid "&Database Connections..."
+msgstr "&Datenbankverbindungen"
+
+#: ../Thuban/UI/mainwindow.py:1171
+msgid "E&xit"
+msgstr "Be&enden"
+
+#: ../Thuban/UI/mainwindow.py:1172
+msgid "Finish working with Thuban"
+msgstr "Arbeiten mit Thuban beenden"
+
+#: ../Thuban/UI/mainwindow.py:1175
+msgid "&About..."
+msgstr "&Über..."
+
+#: ../Thuban/UI/mainwindow.py:1176
+msgid "Info about Thuban authors, version and modules"
+msgstr ""
+"Informationen über die Autoren von Thuban, die Version und die verwendeten "
+"Module"
+
+#: ../Thuban/UI/mainwindow.py:1180 ../Thuban/UI/mainwindow.py:1228
+msgid "Pro&jection..."
+msgstr "Pro&jektion..."
+
+#: ../Thuban/UI/mainwindow.py:1181
+msgid "Set or change the map projection"
+msgstr "Setze oder ändere die Kartenprojektion"
+
+#: ../Thuban/UI/mainwindow.py:1183
+msgid "&Zoom in"
+msgstr "Hine&inzoomen"
+
+#: ../Thuban/UI/mainwindow.py:1184
+msgid "Switch to map-mode 'zoom-in'"
+msgstr "Hineinzoomen"
+
+#: ../Thuban/UI/mainwindow.py:1186
+msgid "Zoom &out"
+msgstr "Her&auszoomen"
+
+#: ../Thuban/UI/mainwindow.py:1187
+msgid "Switch to map-mode 'zoom-out'"
+msgstr "Herauszoomen"
+
+#: ../Thuban/UI/mainwindow.py:1189
+msgid "&Pan"
+msgstr "&Verschieben"
+
+#: ../Thuban/UI/mainwindow.py:1190
+msgid "Switch to map-mode 'pan'"
+msgstr "Verschieben"
+
+#: ../Thuban/UI/mainwindow.py:1192
+msgid "&Identify"
+msgstr "&Identifizieren"
+
+#: ../Thuban/UI/mainwindow.py:1194
+msgid "Switch to map-mode 'identify'"
+msgstr "Identifizieren"
+
+#: ../Thuban/UI/mainwindow.py:1196
+msgid "&Label"
+msgstr "&Label"
+
+#: ../Thuban/UI/mainwindow.py:1197
+msgid "Add/Remove labels"
+msgstr "Labels hinzufügen/entfernen"
+
+#: ../Thuban/UI/mainwindow.py:1199
+msgid "&Full extent"
+msgstr "Volle Ausdehnung"
+
+#: ../Thuban/UI/mainwindow.py:1200
+msgid "Zoom to the full map extent"
+msgstr "Zur vollen Kartenausdehnung zoomen"
+
+#: ../Thuban/UI/mainwindow.py:1202
+msgid "&Full layer extent"
+msgstr "Volle Ebenenausdehnung"
+
+#: ../Thuban/UI/mainwindow.py:1203
+msgid "Zoom to the full layer extent"
+msgstr "Zur vollen Ebenenausdehnung zoomen"
+
+#: ../Thuban/UI/mainwindow.py:1205
+msgid "&Full selection extent"
+msgstr "Volle Auswahlausdehnung"
+
+#: ../Thuban/UI/mainwindow.py:1207
+msgid "Zoom to the full selection extent"
+msgstr "Zur vollen Auswahlausdehnung zoomen"
+
+#: ../Thuban/UI/mainwindow.py:1209
+msgid "E&xport"
+msgstr "E&xport"
+
+#: ../Thuban/UI/mainwindow.py:1210
+msgid "Export the map to file"
+msgstr "Exportiere die Karte in die Datei"
+
+#: ../Thuban/UI/mainwindow.py:1211
+msgid "Prin&t"
+msgstr "&Drucken"
+
+#: ../Thuban/UI/mainwindow.py:1212
+msgid "Print the map"
+msgstr "Karte drucken"
+
+#: ../Thuban/UI/mainwindow.py:1213 ../Thuban/UI/mainwindow.py:1299
+msgid "&Rename..."
+msgstr "&Umbenennen..."
+
+#: ../Thuban/UI/mainwindow.py:1214
+msgid "Rename the map"
+msgstr "Karte umbenennen"
+
+#: ../Thuban/UI/mainwindow.py:1215
+msgid "&Add Layer..."
+msgstr "Ebene &hinzufügen"
+
+#: ../Thuban/UI/mainwindow.py:1216
+msgid "Add a new layer to the map"
+msgstr "Eine neue Ebene zur Karte hinzufügen"
+
+#: ../Thuban/UI/mainwindow.py:1217
+msgid "&Add Image Layer..."
+msgstr "&Bildebene hinzufügen..."
+
+#: ../Thuban/UI/mainwindow.py:1218
+msgid "Add a new image layer to the map"
+msgstr "Eine neue Bildebene zur Karte hinzufügen"
+
+#: ../Thuban/UI/mainwindow.py:1220
+msgid "Add &Database Layer..."
+msgstr "&Datenbankebene hinzufügen..."
+
+#: ../Thuban/UI/mainwindow.py:1221
+msgid "Add a new database layer to active map"
+msgstr "Eine neue Bildebene aus einer Datenbank zur Karte hinzufügen"
+
+#: ../Thuban/UI/mainwindow.py:1223
+msgid "&Remove Layer"
+msgstr "Ebene &entfernen"
+
+#: ../Thuban/UI/mainwindow.py:1224
+msgid "Remove selected layer"
+msgstr "Ausgewählte Ebene entfernen"
+
+#: ../Thuban/UI/mainwindow.py:1230
+msgid "Specify projection for selected layer"
+msgstr "Projektion für die ausgewählte Ebene spezifizieren"
+
+#: ../Thuban/UI/mainwindow.py:1231
+msgid "&Duplicate"
+msgstr "&Duplizieren"
+
+#: ../Thuban/UI/mainwindow.py:1232
+msgid "Duplicate selected layer"
+msgstr "Ausgewählte Ebene duplizieren"
+
+#: ../Thuban/UI/mainwindow.py:1234
+msgid "Re&name ..."
+msgstr "&Umbenennen..."
+
+#: ../Thuban/UI/mainwindow.py:1235
+msgid "Rename selected layer"
+msgstr "Ausgewählte Ebene umbenennen"
+
+#: ../Thuban/UI/mainwindow.py:1237
+msgid "&Raise"
+msgstr "Eine Ebene nach &oben bewegen"
+
+#: ../Thuban/UI/mainwindow.py:1238
+msgid "Raise selected layer"
+msgstr "Ausgewählte Ebene eine Ebene nach oben bewegen"
+
+#: ../Thuban/UI/mainwindow.py:1240
+msgid "&Lower"
+msgstr "Eine Ebene nach &unten bewegen"
+
+#: ../Thuban/UI/mainwindow.py:1241
+msgid "Lower selected layer"
+msgstr "Ausgewählte Ebene eine Ebene nach unten bewegen"
+
+#: ../Thuban/UI/mainwindow.py:1243
+msgid "&Show"
+msgstr "&Sichtbar"
+
+#: ../Thuban/UI/mainwindow.py:1244
+msgid "Make selected layer visible"
+msgstr "Ausgewählte Ebene ist sichtbar"
+
+#: ../Thuban/UI/mainwindow.py:1246
+msgid "&Hide"
+msgstr "&Nicht sichtbar"
+
+#: ../Thuban/UI/mainwindow.py:1247
+msgid "Make selected layer unvisible"
+msgstr "Ausgewählte Ebene ist nicht sichtbar"
+
+#: ../Thuban/UI/mainwindow.py:1249
+msgid "Show Ta&ble"
+msgstr "&Zeige Tabelle"
+
+#: ../Thuban/UI/mainwindow.py:1250
+msgid "Show the selected layer's table"
+msgstr "Die Tabelle zur ausgewählten Ebene zeigen"
+
+#: ../Thuban/UI/mainwindow.py:1252
+msgid "&Properties..."
+msgstr "&Einstellungen..."
+
+#: ../Thuban/UI/mainwindow.py:1254
+msgid "Edit the properties of the selected layer"
+msgstr "Die Einstellungen der ausgewählten Ebenen bearbeiten"
+
+#: ../Thuban/UI/mainwindow.py:1255
+msgid "&Join Table..."
+msgstr "Tabelle &verbinden..."
+
+#: ../Thuban/UI/mainwindow.py:1257
+msgid "Join and attach a table to the selected layer"
+msgstr "Verbinden und anfügen einer Tabellen zur ausgewählten Ebenen"
+
+#: ../Thuban/UI/mainwindow.py:1260
+msgid "&Top"
+msgstr "&Oben"
+
+#: ../Thuban/UI/mainwindow.py:1261
+msgid "Put selected layer to the top"
+msgstr "Ausgewählte Ebene nach oben stellen"
+
+#: ../Thuban/UI/mainwindow.py:1263
+msgid "&Bottom"
+msgstr "&Unten"
+
+#: ../Thuban/UI/mainwindow.py:1264
+msgid "Put selected layer to the bottom"
+msgstr "Ausgewählte Ebene nach unten stellen"
+
+#: ../Thuban/UI/mainwindow.py:1266
+msgid "&Visible"
+msgstr "&Sichtbar"
+
+#: ../Thuban/UI/mainwindow.py:1268
+msgid "Toggle visibility of selected layer"
+msgstr "Sichtbarkeit der ausgewählten Ebene umschalten"
+
+#: ../Thuban/UI/mainwindow.py:1285
+msgid "&Unjoin Table..."
+msgstr "Verbindungen &lösen"
+
+#: ../Thuban/UI/mainwindow.py:1287
+msgid "Undo the last join operation"
+msgstr "Letzte Verbindungenoperation rückgängig machen"
+
+#: ../Thuban/UI/mainwindow.py:1294
+msgid "&Open..."
+msgstr "&Öffnen..."
+
+#: ../Thuban/UI/mainwindow.py:1295
+msgid "Open a DBF-table from a file"
+msgstr "Öffne eine DBF-Tabelle aus einer Datei"
+
+#: ../Thuban/UI/mainwindow.py:1296
+msgid "&Close..."
+msgstr "&Schließen..."
+
+#: ../Thuban/UI/mainwindow.py:1298
+msgid "Close one or more tables from a list"
+msgstr "Schließe eine oder mehrere Tabellen von der Liste"
+
+#: ../Thuban/UI/mainwindow.py:1301
+msgid "Rename one or more tables"
+msgstr "Umbenennen von einer oder mehreren Tabellen"
+
+#: ../Thuban/UI/mainwindow.py:1302
+msgid "&Show..."
+msgstr "&Zeigen..."
+
+#: ../Thuban/UI/mainwindow.py:1304
+msgid "Show one or more tables in a dialog"
+msgstr "Zeige eine oder mehrere Tabelle in einem Dialog"
+
+#: ../Thuban/UI/mainwindow.py:1305
+msgid "&Join..."
+msgstr "&Verbinden..."
+
+#: ../Thuban/UI/mainwindow.py:1307
+msgid "Join two tables creating a new one"
+msgstr "Verbinde zwei Tabellen erzeuge eine neue Tabelle"
+
+#: ../Thuban/UI/mainwindow.py:1331
+msgid "&File"
+msgstr "&Datei"
+
+#: ../Thuban/UI/mainwindow.py:1337
+msgid "&Map"
+msgstr "&Karte"
+
+#: ../Thuban/UI/mainwindow.py:1338
+msgid "&Layer"
+msgstr "&Ebene"
+
+#: ../Thuban/UI/mainwindow.py:1352
+msgid "&Table"
+msgstr "&Tabelle"
+
+#: ../Thuban/UI/mainwindow.py:1358
+msgid "&Help"
+msgstr "&Hilfe"
+
+#: ../Thuban/UI/menu.py:90
+#, python-format
+msgid "Submenu %s doesn't exist"
+msgstr "Untermenü %s existiert nicht"
+
+#: ../Thuban/UI/projdialog.py:62 ../Thuban/UI/projdialog.py:776
+msgid "Transverse Mercator"
+msgstr "Transverse Mercator"
+
+#: ../Thuban/UI/projdialog.py:63 ../Thuban/UI/projdialog.py:842
+msgid "Universal Transverse Mercator"
+msgstr "Universal Transverse Mercator"
+
+#: ../Thuban/UI/projdialog.py:64 ../Thuban/UI/projdialog.py:918
+msgid "Lambert Conic Conformal"
+msgstr "Lambert Conic Conformal"
+
+#: ../Thuban/UI/projdialog.py:65 ../Thuban/UI/projdialog.py:66
+#: ../Thuban/UI/projdialog.py:968
+msgid "Geographic"
+msgstr "Geographisch"
+
+#: ../Thuban/UI/projdialog.py:110
+msgid "Import..."
+msgstr "Import..."
+
+#: ../Thuban/UI/projdialog.py:113
+msgid "Export..."
+msgstr "Export..."
+
+#: ../Thuban/UI/projdialog.py:122
+msgid "Show EPSG:"
+msgstr "EPSG Anzeigen:"
+
+#: ../Thuban/UI/projdialog.py:124
+msgid "Normal"
+msgstr "Normal"
+
+#: ../Thuban/UI/projdialog.py:127
+msgid "Deprecated"
+msgstr "Veraltet"
+
+#: ../Thuban/UI/projdialog.py:138
+msgid "Edit"
+msgstr "Bearbeiten"
+
+#: ../Thuban/UI/projdialog.py:148
+msgid "Name:"
+msgstr "Name:"
+
+#: ../Thuban/UI/projdialog.py:156
+msgid "Projection:"
+msgstr "Projektion:"
+
+#: ../Thuban/UI/projdialog.py:167 ../Thuban/UI/projdialog.py:648
+msgid "<Unknown>"
+msgstr "<Unbekannt>"
+
+#: ../Thuban/UI/projdialog.py:183
+msgid "New"
+msgstr "Neu"
+
+#: ../Thuban/UI/projdialog.py:186
+msgid "Add to List"
+msgstr "Hinzufügen zur Liste"
+
+#: ../Thuban/UI/projdialog.py:190
+msgid "Update"
+msgstr "Aktualisieren"
+
+#: ../Thuban/UI/projdialog.py:295
+#, python-format
+msgid ""
+"Warnings when reading \"%s\":\n"
+"\n"
+"%s"
+msgstr ""
+"Warnungen beim Lesen von '%s':\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/projdialog.py:306
+msgid "Import"
+msgstr "Import"
+
+#: ../Thuban/UI/projdialog.py:319 ../Thuban/UI/projdialog.py:617
+msgid "Warnings"
+msgstr "Warnungen"
+
+#: ../Thuban/UI/projdialog.py:337 ../Thuban/UI/tableview.py:386
+msgid "Export"
+msgstr "Export"
+
+#: ../Thuban/UI/projdialog.py:389
+msgid "The following error occured:\n"
+msgstr "Der folgende Fehler trat auf:\n"
+
+#: ../Thuban/UI/projdialog.py:391
+msgid "Error"
+msgstr "Fehler"
+
+#: ../Thuban/UI/projdialog.py:460
+msgid "No Projections selected"
+msgstr "Keine Projektionen Ausgewählt:"
+
+#: ../Thuban/UI/projdialog.py:470
+#, python-format
+msgid "Source of Projection: %s"
+msgstr "Quelle der Projektionen: %s"
+
+#: ../Thuban/UI/projdialog.py:502
+msgid "Multiple Projections selected"
+msgstr "Mehrere Projektionen Ausgewählt"
+
+#: ../Thuban/UI/projdialog.py:649
+msgid "Airy"
+msgstr "Airy"
+
+#: ../Thuban/UI/projdialog.py:650
+msgid "Bessel 1841"
+msgstr "Bessel 1841"
+
+#: ../Thuban/UI/projdialog.py:651
+msgid "Clarke 1866"
+msgstr "Clarke 1866"
+
+#: ../Thuban/UI/projdialog.py:652
+msgid "Clarke 1880"
+msgstr "Clarke 1880"
+
+#: ../Thuban/UI/projdialog.py:653
+msgid "GRS 1980 (IUGG, 1980)"
+msgstr "GRS 1980 (IUGG, 1980)"
+
+#: ../Thuban/UI/projdialog.py:654
+msgid "International 1909 (Hayford)"
+msgstr "International 1909 (Hayford)"
+
+#: ../Thuban/UI/projdialog.py:655
+msgid "WGS 84"
+msgstr "WGS 84"
+
+#: ../Thuban/UI/projdialog.py:667
+msgid "Ellipsoid:"
+msgstr "Rotationsellipsoid"
+
+#: ../Thuban/UI/projdialog.py:716
+msgid ""
+"Thuban does not know the parameters\n"
+"for the current projection and cannot\n"
+"display a configuration panel.\n"
+"\n"
+"The unidentified set of parameters is:\n"
+"\n"
+msgstr ""
+"Thuban kennt die Parameter für\n"
+"die aktuelle Projektion nicht und\n"
+"kann daher das Konfigurationspanel \n"
+"nicht zeigen.\n"
+"\n"
+"Die nicht erkannten Parameter sind:\n"
+"\n"
+
+#: ../Thuban/UI/projdialog.py:762
+msgid "Latitude:"
+msgstr "Breitengrad:"
+
+#: ../Thuban/UI/projdialog.py:764
+msgid "Longitude:"
+msgstr "Längengrad:"
+
+#: ../Thuban/UI/projdialog.py:766 ../Thuban/UI/projdialog.py:910
+msgid "False Easting:"
+msgstr "Falsche Ostausrichtung:"
+
+#: ../Thuban/UI/projdialog.py:768 ../Thuban/UI/projdialog.py:912
+msgid "False Northing:"
+msgstr "Falsche Nordausrichtung:"
+
+#: ../Thuban/UI/projdialog.py:770
+msgid "Scale Factor:"
+msgstr "Skalierungsfaktor:"
+
+#: ../Thuban/UI/projdialog.py:821
+msgid "Propose"
+msgstr "Vorschlagen"
+
+#: ../Thuban/UI/projdialog.py:823
+msgid "Southern Hemisphere"
+msgstr "Südliche Hemisphäre"
+
+#: ../Thuban/UI/projdialog.py:833
+msgid "Zone:"
+msgstr "Zone:"
+
+#: ../Thuban/UI/projdialog.py:870
+msgid "Can not propose: No bounding box found."
+msgstr "Kann nicht vorgeschlagen werden: Da keine Bounding Box gefunden wurde."
+
+#: ../Thuban/UI/projdialog.py:871 ../Thuban/UI/projdialog.py:1008
+msgid "Projection: Propose UTM Zone"
+msgstr "Projektion: Vorschlag UTM Zone"
+
+#: ../Thuban/UI/projdialog.py:901
+msgid "Latitude of first standard parallel:"
+msgstr "Standard-Parallelkreis 1:"
+
+#: ../Thuban/UI/projdialog.py:904
+msgid "Latitude of second standard parallel:"
+msgstr "Standard-Parallelkreis 2:"
+
+#: ../Thuban/UI/projdialog.py:906
+msgid "Central Meridian:"
+msgstr "Zentraler Meridian:"
+
+#: ../Thuban/UI/projdialog.py:908
+msgid "Latitude of origin:"
+msgstr "Geographische Breitenreferenz:"
+
+#: ../Thuban/UI/projdialog.py:958
+msgid "Degrees"
+msgstr "Grade"
+
+#: ../Thuban/UI/projdialog.py:959
+msgid "Radians"
+msgstr "Radiant"
+
+#: ../Thuban/UI/projdialog.py:992
+msgid "Source Data is in: "
+msgstr "Quelldaten sind in:"
+
+#: ../Thuban/UI/projdialog.py:1021
+msgid "The current map extent center lies in UTM Zone"
+msgstr "Die gegenwärtige Kartenausdehnung liegt in der UTM Zone"
+
+#: ../Thuban/UI/projdialog.py:1031
+msgid "Take"
+msgstr "Übernehmen"
+
+#: ../Thuban/UI/projlist.py:51
+msgid "Available Projections"
+msgstr "Verfügbare Projektionen"
+
+#: ../Thuban/UI/projlist.py:112
+msgid "<None>"
+msgstr "<Keine>"
+
+#: ../Thuban/UI/projlist.py:117
+#, python-format
+msgid "%s (current)"
+msgstr "%s (aktuell)"
+
+#: ../Thuban/UI/rasterlayerproperties.py:41
+msgid "GDAL image information unavailable. See About box for details."
+msgstr ""
+"GDAL Bildinformation nicht verfügbar. Siehe Hilfe/Über... wegen Details."
+
+#: ../Thuban/UI/rasterlayerproperties.py:49
+msgid "Extent (lat-lon): None"
+msgstr "Ausdehnung (Breite-Länge): Keine"
+
+#: ../Thuban/UI/rasterlayerproperties.py:56
+msgid "Image Properties"
+msgstr "Bildeigenschaften"
+
+#: ../Thuban/UI/rasterlayerproperties.py:61
+#, python-format
+msgid "Source: %s"
+msgstr "Quelle: %s"
+
+#: ../Thuban/UI/rasterlayerproperties.py:71
+#, python-format
+msgid "Driver: %s"
+msgstr "Treiber: %s"
+
+#: ../Thuban/UI/rasterlayerproperties.py:74
+#, python-format
+msgid "Size: %ix%i"
+msgstr "Größe: %ix%i"
+
+#: ../Thuban/UI/rasterlayerproperties.py:77
+#, python-format
+msgid "Number of Bands: %i"
+msgstr "Anzahl der Bänder: %s"
+
+#: ../Thuban/UI/rasterlayerproperties.py:93
+msgid "Mask Type"
+msgstr "Maskentyp"
+
+#: ../Thuban/UI/rasterlayerproperties.py:99
+msgid "Opacity:"
+msgstr "Opazität:"
+
+#: ../Thuban/UI/tableview.py:381
+msgid "Replace Selection"
+msgstr "Ersetze Selektion"
+
+#: ../Thuban/UI/tableview.py:382
+msgid "Refine Selection"
+msgstr "Selektion verfeinern"
+
+#: ../Thuban/UI/tableview.py:383
+msgid "Add to Selection"
+msgstr "Zu Selektion hinzufügen"
+
+#: ../Thuban/UI/tableview.py:385
+msgid "Query"
+msgstr "Abfrage"
+
+#: ../Thuban/UI/tableview.py:387
+msgid "Export Selection"
+msgstr "Selektion exportieren"
+
+#: ../Thuban/UI/tableview.py:413
+msgid "Selection"
+msgstr "Selektion"
+
+#: ../Thuban/UI/tableview.py:455
+#, python-format
+msgid "%i rows (%i selected), %i columns"
+msgstr "%i Zeilen (%i ausgewählt), %i Spalten"
+
+#: ../Thuban/UI/tableview.py:535
+msgid "Export Table To"
+msgstr "Exportiere Tabelle nach"
+
+#: ../Thuban/UI/tableview.py:536
+msgid "DBF Files (*.dbf)|*.dbf|"
+msgstr "DBF Dateien (*.dbf)|*.dbf|"
+
+#: ../Thuban/UI/tableview.py:537
+msgid "CSV Files (*.csv)|*.csv|"
+msgstr "CSV Dateien (*.csv)|*.csv|"
+
+#: ../Thuban/UI/tableview.py:538
+msgid "All Files (*.*)|*.*"
+msgstr "Alle Dateien (*.*)|*.*"
+
+#: ../Thuban/UI/tree.py:226
+msgid "Session"
+msgstr "Sitzung"
+
+#: ../Thuban/UI/view.py:285
+msgid "Export Map"
+msgstr "Exportiere Karte"

Added: packages/thuban/branches/upstream/current/po/es.po
===================================================================
--- packages/thuban/branches/upstream/current/po/es.po	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/po/es.po	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1856 @@
+# Thuban Translation File for Spanish
+# Archivo de Traducción al Castellano de Thuban
+# Copyright (C) 2003
+# This file is distributed under the same license as the Thuban package.
+# Daniel Calvelo (dcalvelo at minag.gob.pe), 2003
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Thuban 1.0Report-Msgid-Bugs-To: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-03-13 20:15+0000\n"
+"PO-Revision-Date: 2003-12-16 14:12-0500\n"
+"Last-Translator: Daniel Calvelo Aros (dcalvelo at minag.gob.pe)\n"
+"Language-Team: Thuban <thuban at intevation.de>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../Thuban/version.py:189
+#, python-format
+msgid "%s %s < %s"
+msgstr "%s %s < %s"
+
+#: ../Thuban/version.py:195
+#, python-format
+msgid "Thuban was compiled with wx %(wxproj-wx)s but wxPython is %(wxPython)s"
+msgstr ""
+
+#: ../Thuban/Lib/connector.py:65
+#, python-format
+msgid "no receivers for channel %s of %s"
+msgstr "no hay receptores para el canal %s de %s"
+
+#: ../Thuban/Lib/connector.py:70
+#, python-format
+msgid "receiver %s%s is not connected to channel %s of %s"
+msgstr "el receptor %s%s no está conectado al canal %s de %s"
+
+#: ../Thuban/Lib/connector.py:94
+#, python-format
+msgid "Warning: %s.%s: %s%s\n"
+msgstr "Advertencia: %s.%s: %s%s\n"
+
+#: ../Thuban/Lib/connector.py:118
+#, python-format
+msgid "\tmethod %s of %s"
+msgstr "\tmétodo %s de %s"
+
+#: ../Thuban/Lib/fileutil.py:87 ../Thuban/Lib/fileutil.py:141
+msgid "first argument must be an absolute filename"
+msgstr "el primer argumento debe ser un nombre de fichero absoluto"
+
+#: ../Thuban/Lib/fileutil.py:138
+msgid "Both parameters must have a drive letter"
+msgstr "Ambos parámetros deben contener una letra de unidad"
+
+#: ../Thuban/Lib/fileutil.py:198
+msgid "No implementation of get_application_dir available for platform"
+msgstr ""
+"No existe una implementación de nombre de get_application_dir para esta "
+"plataforma"
+
+#: ../Thuban/Lib/fileutil.py:208
+msgid "No implementation of relative_filename available for platform"
+msgstr "No existe una implementación de relative_filename para esta plataforma"
+
+#: ../Thuban/Model/classgen.py:338
+msgid "invalid index"
+msgstr "índice no válido"
+
+#: ../Thuban/Model/classification.py:309 ../Thuban/UI/classifier.py:758
+msgid "None"
+msgstr "Ninguno"
+
+#: ../Thuban/Model/classification.py:325
+msgid "Line Color"
+msgstr "Color de Línea"
+
+#: ../Thuban/Model/classification.py:327
+#, python-format
+msgid "Line Width: %s"
+msgstr "Ancho de Línea: %s"
+
+#: ../Thuban/Model/classification.py:333
+#, fuzzy, python-format
+msgid "Size: %s"
+msgstr "Campo: %s"
+
+#: ../Thuban/Model/classification.py:336
+msgid "Fill"
+msgstr "Llenado"
+
+#: ../Thuban/Model/classification.py:342 ../Thuban/UI/classifier.py:841
+msgid "Classification"
+msgstr "Clasificación"
+
+#: ../Thuban/Model/classification.py:436
+msgid "lineWidth < 1"
+msgstr "ancho < 1"
+
+#: ../Thuban/Model/classification.py:451
+msgid "size < 1"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:656 ../Thuban/UI/classifier.py:528
+msgid "DEFAULT"
+msgstr "POR OMISIÓN"
+
+#: ../Thuban/Model/data.py:316
+msgid "Table not compatible with shapestore."
+msgstr "Tabla no compatible con almacén de capas"
+
+#: ../Thuban/Model/extension.py:90
+#, python-format
+msgid "Extension: %s"
+msgstr "Extensión: %s"
+
+#: ../Thuban/Model/label.py:91
+#, fuzzy, python-format
+msgid "Number of labels: %d"
+msgstr "Número de Grupos:"
+
+#: ../Thuban/Model/label.py:92
+#, fuzzy, python-format
+msgid "Label Layer: %s"
+msgstr "Tabla: %s"
+
+#: ../Thuban/Model/layer.py:298 ../Thuban/Model/layer.py:566
+#: ../Thuban/Model/session.py:432
+#, python-format
+msgid "Filename: %s"
+msgstr "Archivo: %s"
+
+#: ../Thuban/Model/layer.py:301 ../Thuban/Model/layer.py:569
+msgid "Shown"
+msgstr "Visible"
+
+#: ../Thuban/Model/layer.py:303 ../Thuban/Model/layer.py:571
+msgid "Hidden"
+msgstr "Oculto"
+
+#: ../Thuban/Model/layer.py:304
+#, python-format
+msgid "Shapes: %d"
+msgstr "Elementos: %d"
+
+#: ../Thuban/Model/layer.py:308 ../Thuban/Model/layer.py:575
+#: ../Thuban/Model/map.py:287 ../Thuban/UI/rasterlayerproperties.py:51
+#, python-format
+msgid "Extent (lat-lon): (%g, %g, %g, %g)"
+msgstr "Cobertura (lat-lon): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/layer.py:310 ../Thuban/Model/layer.py:577
+msgid "Extent (lat-lon):"
+msgstr "Cobertura (lat-lon):"
+
+#: ../Thuban/Model/layer.py:311
+#, python-format
+msgid "Shapetype: %s"
+msgstr "Tipo de capa: %s"
+
+#: ../Thuban/Model/layer.py:314 ../Thuban/Model/layer.py:580
+#: ../Thuban/Model/map.py:292
+msgid "Projection"
+msgstr "Proyección"
+
+#: ../Thuban/Model/layer.py:319 ../Thuban/Model/layer.py:583
+#, python-format
+msgid "Layer '%s'"
+msgstr "Capa '%s'"
+
+#: ../Thuban/Model/load.py:78
+#, python-format
+msgid "Invalid hexadecimal color specification %s"
+msgstr "Especificación hexadecimal de color %s inválida"
+
+#: ../Thuban/Model/load.py:81
+#, python-format
+msgid "Invalid color specification %s"
+msgstr "Especificación de color %s inválida"
+
+#: ../Thuban/Model/load.py:544
+msgid "xml field type differs from database!"
+msgstr "¡el tipo de campo xml es diferente del de la base de datos!"
+
+#: ../Thuban/Model/load.py:609
+msgid "Classification range is not a number!"
+msgstr "¡El rango de la clasificación no es un número!"
+
+#: ../Thuban/Model/map.py:53
+msgid "Labels"
+msgstr "Etiquetas"
+
+#: ../Thuban/Model/map.py:290
+#, python-format
+msgid "Extent (projected): (%g, %g, %g, %g)"
+msgstr "Cobertura (proyectada): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/map.py:301
+#, python-format
+msgid "Map: %s"
+msgstr "Mapa: %s"
+
+#: ../Thuban/Model/proj.py:84 ../Thuban/Model/resource.py:179
+msgid "Unknown"
+msgstr "Desconocido"
+
+#: ../Thuban/Model/resource.py:46
+#, python-format
+msgid ""
+"No GDAL support because module '%s' cannot be imported. Python exception: '%"
+"s'"
+msgstr ""
+"No hay soporte para GDAL, porque el módulo '%s' no pudo ser importado. La "
+"excepción de Python fue \"%s\""
+
+#: ../Thuban/Model/resource.py:135 ../Thuban/Model/resource.py:155
+#, python-format
+msgid "Could not read \"%s\": %s"
+msgstr "No se pudo leer \"%s\": %s"
+
+#: ../Thuban/Model/resource.py:187
+#, python-format
+msgid "Error in projection \"%s\": %s"
+msgstr "Error en la Proyección \"%s\": %s"
+
+#: ../Thuban/Model/save.py:352
+msgid "Unsupported group type in classification"
+msgstr "Tipo de Grupo no implementado en la clasificación"
+
+#: ../Thuban/Model/session.py:430
+msgid "Filename:"
+msgstr "Archivo:"
+
+#: ../Thuban/Model/session.py:435
+msgid "Modified"
+msgstr "Modificado"
+
+#: ../Thuban/Model/session.py:437
+msgid "Unmodified"
+msgstr "No modificado"
+
+#: ../Thuban/Model/session.py:442
+#, python-format
+msgid "Session: %s"
+msgstr "Sesión: %s"
+
+#: ../Thuban/Model/session.py:448
+msgid "unnamed session"
+msgstr "sesión sin nombre"
+
+#: ../Thuban/Model/session.py:450
+msgid "unnamed map"
+msgstr "mapa sin título"
+
+#: ../Thuban/UI/about.py:28
+msgid "About Thuban"
+msgstr "Sobre Thuban"
+
+#: ../Thuban/UI/about.py:47
+msgid "French"
+msgstr "Francés"
+
+#: ../Thuban/UI/about.py:48
+msgid "German"
+msgstr "Alemán"
+
+#: ../Thuban/UI/about.py:50
+msgid "Hungarian"
+msgstr ""
+
+#: ../Thuban/UI/about.py:51
+msgid "Italian"
+msgstr "Italiano"
+
+#: ../Thuban/UI/about.py:52
+msgid "Portuguese (Brazilian)"
+msgstr ""
+
+#: ../Thuban/UI/about.py:53
+msgid "Russian"
+msgstr "Ruso"
+
+#: ../Thuban/UI/about.py:54
+msgid "Spanish"
+msgstr "Castellano"
+
+#: ../Thuban/UI/about.py:63 ../Thuban/UI/about.py:65 ../Thuban/UI/about.py:67
+msgid "- not available"
+msgstr "- no disponible"
+
+#: ../Thuban/UI/about.py:72
+msgid "Currently using:\n"
+msgstr "Usando actualmente:\n"
+
+#: ../Thuban/UI/about.py:78
+#, python-format
+msgid "\tInternal encoding: %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:84
+msgid "Compiled for:\n"
+msgstr "Compilado para:\n"
+
+#: ../Thuban/UI/about.py:90
+#, fuzzy
+msgid "Extensions:\n"
+msgstr "Extensión: %s"
+
+#: ../Thuban/UI/about.py:95 ../Thuban/UI/about.py:144
+msgid "\tNone registered.\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:98
+msgid "Maintainers:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:103
+msgid "Lead Developer:\n"
+msgstr "Programador Principal:\n"
+
+#: ../Thuban/UI/about.py:106
+msgid "Developers:\n"
+msgstr "Programadores:\n"
+
+#: ../Thuban/UI/about.py:111
+msgid "Translators:\n"
+msgstr "Traductores:\n"
+
+#: ../Thuban/UI/about.py:116
+msgid "Other Contributors:\n"
+msgstr "Otros Colaboradores\n"
+
+#: ../Thuban/UI/about.py:122
+#, fuzzy
+msgid ""
+"Questions and comments can be sent to the following addresses:\n"
+"\tGeneral list (public):\n"
+"\t\t<thuban-list at intevation.de>\n"
+"\tDevelopers list (public):\n"
+"\t\t<thuban-devel at intevation.de>\n"
+"\tThuban team at Intevation:\n"
+"\t\t<thuban at intevation.de>\n"
+msgstr ""
+"Envíe preguntas y comentarios a las siguientes direcciones electrónicas:\n"
+"\tDesarrollo de Thuban:\n"
+"\t\t<thuban at intevation.de>\n"
+"\tLista de difusión acerca de Thuban:\n"
+"\t\t<thuban-list at intevation.de>"
+
+#: ../Thuban/UI/about.py:130
+msgid ""
+"Details on the registered extensions:\n"
+"\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:135
+#, python-format
+msgid "Copyright %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:136
+msgid "Authors:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:149
+msgid ""
+"Thuban is a program for exploring geographic data.\n"
+"\n"
+msgstr ""
+"Thuban es un programa para la exploración de datos geográficos\n"
+"\n"
+
+#: ../Thuban/UI/about.py:151
+msgid "Thuban is licensed under the GNU GPL"
+msgstr "Thuban es distribuido bajo la licencia GPL de GNU"
+
+#: ../Thuban/UI/about.py:160 ../Thuban/UI/classgen.py:91
+#: ../Thuban/UI/dbdialog.py:276 ../Thuban/UI/dock.py:371
+#: ../Thuban/UI/join.py:66 ../Thuban/UI/layerproperties.py:82
+#: ../Thuban/UI/projdialog.py:209 ../Thuban/UI/tableview.py:388
+msgid "Close"
+msgstr "Cerrar"
+
+#: ../Thuban/UI/altpathdialog.py:24
+#, fuzzy, python-format
+msgid "Select an alternative data file for %s"
+msgstr "Seleccione uno o más archivos de datos"
+
+#: ../Thuban/UI/altpathdialog.py:31 ../Thuban/UI/mainwindow.py:563
+msgid "Shapefiles (*.shp)"
+msgstr "Shapefiles (*.shp)"
+
+#: ../Thuban/UI/altpathdialog.py:32 ../Thuban/UI/mainwindow.py:564
+#: ../Thuban/UI/mainwindow.py:852
+msgid "All Files (*.*)"
+msgstr "Todos (*.*)"
+
+#: ../Thuban/UI/altpathdialog.py:47
+#, python-format
+msgid ""
+"Found the following as an alternative for %s.\n"
+"%s\n"
+"\n"
+" Please confirm with Yes or select alternative with No."
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:49
+msgid "Alternative Path"
+msgstr ""
+
+#: ../Thuban/UI/application.py:110 ../Thuban/UI/application.py:122
+msgid "Cannot import the thubanstart module\n"
+msgstr "No se pudo importar el módulo de inicio thubanstart\n"
+
+#: ../Thuban/UI/application.py:115
+msgid "No thubanstart module available\n"
+msgstr "El módulo de inicio thubanstart no está disponible\n"
+
+#: ../Thuban/UI/application.py:126
+msgid "No ~/.thuban directory\n"
+msgstr "No existe el directorio ~/.thuban\n"
+
+#: ../Thuban/UI/application.py:166
+msgid ""
+"This is the wxPython-based Graphical User Interface for exploring geographic "
+"data"
+msgstr ""
+"Esta es la Interfase Gráfica basada en wxPython para la exploración de datos "
+"geográficos"
+
+#: ../Thuban/UI/application.py:254
+msgid ""
+"The current session contains Image layers,\n"
+"but the GDAL library is not available to draw them."
+msgstr ""
+"La sesión actual contiene capas de imagen,\n"
+"pero la biblioteca GDAL no está disponible para dibujarlas."
+
+#: ../Thuban/UI/application.py:259
+msgid "Library not available"
+msgstr "Biblioteca no disponible"
+
+#: ../Thuban/UI/application.py:268 ../Thuban/UI/mainwindow.py:476
+msgid "DB Connection Parameters"
+msgstr "Parámetros de Conexión a Base de Datos"
+
+#: ../Thuban/UI/application.py:364
+#, python-format
+msgid ""
+"An unhandled exception occurred:\n"
+"%s\n"
+"(please report to http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+msgstr ""
+"Se activó una excepción no manejada:\n"
+"%s\n"
+"(por favior informe del error utilizando http://thuban.intevation.org/"
+"bugtracker.html)\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/classgen.py:43
+msgid "Uniform Distribution"
+msgstr "Distribución Uniforme"
+
+#: ../Thuban/UI/classgen.py:44
+msgid "Unique Values"
+msgstr "Valores únicos"
+
+#: ../Thuban/UI/classgen.py:45
+msgid "Quantiles from Table"
+msgstr "Cuantiles a partir de la Tabla"
+
+#: ../Thuban/UI/classgen.py:47
+msgid "Custom Ramp"
+msgstr "Rampa Propia"
+
+#: ../Thuban/UI/classgen.py:48
+msgid "Grey Ramp"
+msgstr "Rampa Gris"
+
+#: ../Thuban/UI/classgen.py:49
+msgid "Red Ramp"
+msgstr "Rampa Roja"
+
+#: ../Thuban/UI/classgen.py:50
+msgid "Green Ramp"
+msgstr "Rampa Verde"
+
+#: ../Thuban/UI/classgen.py:51
+msgid "Blue Ramp"
+msgstr "Rampa Azul"
+
+#: ../Thuban/UI/classgen.py:52
+msgid "Green-to-Red Ramp"
+msgstr "Rampa Verde a Azul"
+
+#: ../Thuban/UI/classgen.py:53
+msgid "Hot-to-Cold Ramp"
+msgstr "Rampa Cálidos a Fríos"
+
+#: ../Thuban/UI/classgen.py:69
+msgid "Generate Classification"
+msgstr "Generar Clasificación"
+
+#: ../Thuban/UI/classgen.py:90
+msgid "Generate"
+msgstr "Generar"
+
+#: ../Thuban/UI/classgen.py:119
+#, python-format
+msgid "Field: %s"
+msgstr "Campo: %s"
+
+#: ../Thuban/UI/classgen.py:123 ../Thuban/UI/classifier.py:976
+#, python-format
+msgid "Data Type: %s"
+msgstr "Tipo de Datos: %s"
+
+#: ../Thuban/UI/classgen.py:127
+msgid "Generate:"
+msgstr "Generar:"
+
+#: ../Thuban/UI/classgen.py:137
+msgid "Color Scheme:"
+msgstr "Esquema de Colores:"
+
+#: ../Thuban/UI/classgen.py:161
+msgid "Fix Border Color"
+msgstr "Fijar Color de Línea"
+
+#: ../Thuban/UI/classgen.py:168 ../Thuban/UI/classgen.py:936
+#: ../Thuban/UI/classgen.py:967
+msgid "Change"
+msgstr "Cambiar"
+
+#: ../Thuban/UI/classgen.py:274
+msgid ""
+"Based on the data from the table and the input\n"
+"values, the exact quantiles could not be generated.\n"
+"\n"
+"Accept a close estimate?"
+msgstr ""
+"En base a los datos de la tabla y los valores\n"
+"ingresados, no se pudo generar cuantiles exactos.\n"
+"\n"
+"¿Acepta un buen estimado? "
+
+#: ../Thuban/UI/classgen.py:277
+msgid "Problem with Quantiles"
+msgstr "Problemas en cuantiles"
+
+#: ../Thuban/UI/classgen.py:370
+msgid "Min:"
+msgstr "Min:"
+
+#: ../Thuban/UI/classgen.py:375
+msgid "Max:"
+msgstr "Max:"
+
+#: ../Thuban/UI/classgen.py:380 ../Thuban/UI/classgen.py:633
+msgid "Retrieve From Table"
+msgstr "Tomar de la Tabla"
+
+#: ../Thuban/UI/classgen.py:390
+msgid "Number of Groups:"
+msgstr "Número de Grupos:"
+
+#: ../Thuban/UI/classgen.py:397
+msgid "Stepping:"
+msgstr "Espaciado:"
+
+#: ../Thuban/UI/classgen.py:647
+#, fuzzy
+msgid "Available"
+msgstr "- no disponible"
+
+#: ../Thuban/UI/classgen.py:652 ../Thuban/UI/classgen.py:692
+msgid "Sort"
+msgstr "Ordenar"
+
+#: ../Thuban/UI/classgen.py:655 ../Thuban/UI/classgen.py:695
+msgid "Reverse"
+msgstr "Invertir"
+
+#: ../Thuban/UI/classgen.py:687
+#, fuzzy
+msgid "Use"
+msgstr "Usuario:"
+
+#: ../Thuban/UI/classgen.py:832
+msgid "Retrieve from Table"
+msgstr "Tomar de la Tabla"
+
+#: ../Thuban/UI/classgen.py:840
+msgid "Apply to Range"
+msgstr "Aplicar al Rango"
+
+#: ../Thuban/UI/classgen.py:847
+msgid "Number of Classes:"
+msgstr "Número de Grupos:"
+
+#: ../Thuban/UI/classgen.py:930
+msgid "Start:"
+msgstr "Inicio:"
+
+#: ../Thuban/UI/classgen.py:961
+msgid "End:"
+msgstr "Fin:"
+
+#: ../Thuban/UI/classifier.py:164
+msgid "The Default group cannot be removed."
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:309
+#: ../Thuban/UI/classifier.py:467
+msgid "Pattern"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:306
+#: ../Thuban/UI/classifier.py:466
+msgid "Singleton"
+msgstr "Valor Único"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Visible"
+msgstr "Visible"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Symbol"
+msgstr "Símbolo"
+
+#: ../Thuban/UI/classifier.py:317 ../Thuban/UI/controls.py:33
+#: ../Thuban/UI/controls.py:177
+msgid "Value"
+msgstr "Valor"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Label"
+msgstr "Etiqueta"
+
+#: ../Thuban/UI/classifier.py:462 ../Thuban/UI/classifier.py:465
+msgid "Default"
+msgstr "Por Omisión"
+
+#: ../Thuban/UI/classifier.py:468
+msgid "Range"
+msgstr "Rango"
+
+#: ../Thuban/UI/classifier.py:469
+msgid "Map"
+msgstr "Mapa"
+
+#: ../Thuban/UI/classifier.py:759
+msgid "Text"
+msgstr "Texto"
+
+#: ../Thuban/UI/classifier.py:760
+msgid "Integer"
+msgstr "Entero"
+
+#: ../Thuban/UI/classifier.py:761
+msgid "Decimal"
+msgstr "Decimal"
+
+#: ../Thuban/UI/classifier.py:820
+msgid "Generate Class"
+msgstr "Generar Clases"
+
+#: ../Thuban/UI/classifier.py:822 ../Thuban/UI/dbdialog.py:274
+msgid "Add"
+msgstr "Añadir"
+
+#: ../Thuban/UI/classifier.py:824
+msgid "Move Up"
+msgstr "Elevar"
+
+#: ../Thuban/UI/classifier.py:826
+msgid "Move Down"
+msgstr "Bajar"
+
+#: ../Thuban/UI/classifier.py:828
+msgid "Edit Symbol"
+msgstr "Editar Símbolo"
+
+#: ../Thuban/UI/classifier.py:830 ../Thuban/UI/dbdialog.py:275
+#: ../Thuban/UI/projdialog.py:117
+msgid "Remove"
+msgstr "Eliminar"
+
+#: ../Thuban/UI/classifier.py:845
+msgid "Field: "
+msgstr "Campo: "
+
+#: ../Thuban/UI/classifier.py:1000 ../Thuban/UI/layerproperties.py:160
+msgid "Layer Properties"
+msgstr "Propiedades de la Capa"
+
+#: ../Thuban/UI/classifier.py:1167
+msgid "Select Properties"
+msgstr "Seleccionar Propiedades"
+
+#: ../Thuban/UI/classifier.py:1178
+msgid "Preview:"
+msgstr "Previsualización:"
+
+#: ../Thuban/UI/classifier.py:1195
+msgid "Change Line Color"
+msgstr "Cambiar Color de Línea"
+
+#: ../Thuban/UI/classifier.py:1201 ../Thuban/UI/classifier.py:1216
+msgid "Transparent"
+msgstr "Transparente"
+
+#: ../Thuban/UI/classifier.py:1212
+msgid "Change Fill Color"
+msgstr "Cambiar Color de Llenado"
+
+#: ../Thuban/UI/classifier.py:1225
+msgid "Line Width: "
+msgstr "Ancho de Línea: "
+
+#: ../Thuban/UI/classifier.py:1242
+#, fuzzy
+msgid "Size: "
+msgstr "Título: "
+
+#: ../Thuban/UI/classifier.py:1262 ../Thuban/UI/colordialog.py:52
+#: ../Thuban/UI/dbdialog.py:107 ../Thuban/UI/dbdialog.py:221
+#: ../Thuban/UI/labeldialog.py:41 ../Thuban/UI/layerproperties.py:81
+#: ../Thuban/UI/projdialog.py:205
+msgid "OK"
+msgstr "Aceptar"
+
+#: ../Thuban/UI/classifier.py:1264 ../Thuban/UI/colordialog.py:53
+#: ../Thuban/UI/dbdialog.py:110 ../Thuban/UI/dbdialog.py:223
+#: ../Thuban/UI/labeldialog.py:42 ../Thuban/UI/projdialog.py:1033
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: ../Thuban/UI/colordialog.py:39
+#, fuzzy
+msgid "Select Color"
+msgstr "Selección"
+
+#: ../Thuban/UI/controls.py:31
+msgid "Field"
+msgstr "Campo"
+
+#: ../Thuban/UI/dbdialog.py:41
+msgid "Choose layer from database"
+msgstr "Escoja una capa de la base de datos"
+
+#: ../Thuban/UI/dbdialog.py:59
+msgid "Databases"
+msgstr "Bases de Datos"
+
+#: ../Thuban/UI/dbdialog.py:74
+msgid "Retrieve"
+msgstr "Recuperar"
+
+#: ../Thuban/UI/dbdialog.py:82
+msgid "Tables"
+msgstr "Tablas"
+
+#: ../Thuban/UI/dbdialog.py:92
+msgid "ID Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:98
+msgid "Geometry Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:187
+msgid "Hostname:"
+msgstr "Nombre de Host:"
+
+#: ../Thuban/UI/dbdialog.py:191
+msgid "Port:"
+msgstr "Puerto:"
+
+#: ../Thuban/UI/dbdialog.py:198
+msgid "Database Name:"
+msgstr "Nombre de la Base de Datos:"
+
+#: ../Thuban/UI/dbdialog.py:206
+msgid "User:"
+msgstr "Usuario:"
+
+#: ../Thuban/UI/dbdialog.py:211
+msgid "Password:"
+msgstr "Contraseña:"
+
+#: ../Thuban/UI/dbdialog.py:286
+msgid "Database Management"
+msgstr "Gestión de Bases de Datos"
+
+#: ../Thuban/UI/dbdialog.py:361 ../Thuban/UI/dbdialog.py:366
+msgid "Add Database"
+msgstr "Añadir Base de Datos"
+
+#: ../Thuban/UI/dbdialog.py:367
+#, python-format
+msgid "Connection '%s' already exists"
+msgstr "La conexión '%s' ya existe"
+
+#: ../Thuban/UI/dbdialog.py:388
+msgid "Remove Database Connection"
+msgstr "Eliminar Conexión a Base de Datos"
+
+#: ../Thuban/UI/dbdialog.py:389
+#, python-format
+msgid ""
+"The connection %s\n"
+"is still in use"
+msgstr ""
+"La Conexión %s\n"
+"está siendo usada"
+
+#: ../Thuban/UI/dock.py:190
+msgid "Undock"
+msgstr "Liberar"
+
+#: ../Thuban/UI/dock.py:218
+msgid "Dock"
+msgstr "Estacionar"
+
+#: ../Thuban/UI/exceptiondialog.py:23 ../Thuban/UI/exceptiondialog.py:61
+msgid "Thuban: Internal Error"
+msgstr "Thuban: Error Interno"
+
+#: ../Thuban/UI/exceptiondialog.py:43
+msgid "Proceed"
+msgstr "Ejecutar"
+
+#: ../Thuban/UI/exceptiondialog.py:44
+msgid "Exit Thuban now"
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:72
+msgid "Initialization not yet requested."
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:88
+msgid "Initialization successful."
+msgstr ""
+
+#: ../Thuban/UI/identifyview.py:44
+msgid "Identify Shape"
+msgstr "Identificar"
+
+#: ../Thuban/UI/identifyview.py:56
+msgid "Close Window"
+msgstr "Cerrar Ventana"
+
+#: ../Thuban/UI/identifyview.py:57
+msgid "Stop Identify Mode"
+msgstr "Desactivar Modo Identificar"
+
+#: ../Thuban/UI/join.py:64
+msgid "Join"
+msgstr "Unir"
+
+#: ../Thuban/UI/join.py:71 ../Thuban/UI/join.py:72
+#, fuzzy
+msgid "Select..."
+msgstr "Selección"
+
+#: ../Thuban/UI/join.py:100 ../Thuban/UI/join.py:108
+msgid "Table:"
+msgstr "Tabla:"
+
+#: ../Thuban/UI/join.py:111 ../Thuban/UI/join.py:114
+msgid "Field:"
+msgstr "Campo: "
+
+#: ../Thuban/UI/join.py:125
+msgid "Outer Join (preserves left table records)"
+msgstr "Unión externa (conserva los registros de la tabla izquierda)"
+
+#: ../Thuban/UI/join.py:173
+#, python-format
+msgid ""
+"Join failed:\n"
+"  %s"
+msgstr ""
+"La unión falló:\n"
+"  %s"
+
+#: ../Thuban/UI/join.py:174
+msgid "Info"
+msgstr "Información"
+
+#: ../Thuban/UI/join.py:195
+#, python-format
+msgid ""
+"The joined table has %(joined)d rows but it must have %(needed)d rows to be "
+"used with the selected layer"
+msgstr ""
+"La table que está uniendo tiene %(joined)d líneas pero debe tener %(needed)d "
+"líneas para poder ser utilizada con la capa seleccionada"
+
+#: ../Thuban/UI/join.py:200
+msgid "Join Failed"
+msgstr "La unión falló"
+
+#: ../Thuban/UI/join.py:209 ../Thuban/UI/mainwindow.py:915
+#, python-format
+msgid "Table: %s"
+msgstr "Tabla: %s"
+
+#: ../Thuban/UI/labeldialog.py:26
+msgid "Label Values"
+msgstr "Valores de Etiqueta"
+
+#: ../Thuban/UI/layerproperties.py:54
+msgid "Title: "
+msgstr "Título: "
+
+#: ../Thuban/UI/layerproperties.py:65
+#, fuzzy, python-format
+msgid "Layer Type: %s"
+msgstr "Tabla: %s"
+
+#: ../Thuban/UI/layerproperties.py:71
+#, fuzzy
+msgid "Projection: None"
+msgstr "Proyección:"
+
+#: ../Thuban/UI/layerproperties.py:73
+#, fuzzy, python-format
+msgid "Projection: %s"
+msgstr "Proyección:"
+
+#: ../Thuban/UI/layerproperties.py:79 ../Thuban/UI/projdialog.py:199
+msgid "Try"
+msgstr "Probar"
+
+#: ../Thuban/UI/layerproperties.py:80 ../Thuban/UI/projdialog.py:202
+msgid "Revert"
+msgstr "Revertir"
+
+#: ../Thuban/UI/legend.py:75
+msgid "Top Layer"
+msgstr "Capa Superior"
+
+#: ../Thuban/UI/legend.py:79
+msgid "Raise Layer"
+msgstr "Elevar Capa"
+
+#: ../Thuban/UI/legend.py:83
+msgid "Lower Layer"
+msgstr "Bajar Capa"
+
+#: ../Thuban/UI/legend.py:87
+msgid "Bottom Layer"
+msgstr "Capa Inferior"
+
+#: ../Thuban/UI/legend.py:91
+msgid "Show Layer"
+msgstr "Mostrar Capa"
+
+#: ../Thuban/UI/legend.py:95
+msgid "Hide Layer"
+msgstr "Ocultar Capa"
+
+#: ../Thuban/UI/legend.py:99
+msgid "Edit Layer Properties"
+msgstr "Editar Propiedades de la Capa"
+
+#: ../Thuban/UI/mainwindow.py:264 ../Thuban/UI/mainwindow.py:286
+#, python-format
+msgid "Unknown command %s"
+msgstr "Comando Desconocido %s"
+
+#: ../Thuban/UI/mainwindow.py:299
+#, python-format
+msgid "Unknown command ID %d"
+msgstr "ID de comando desconocida %d"
+
+#: ../Thuban/UI/mainwindow.py:338
+#, python-format
+msgid "The Dialog named %s is already open"
+msgstr "La Ventana de Diálogo %s ya está abierta"
+
+#: ../Thuban/UI/mainwindow.py:396
+#, python-format
+msgid "Select layer '%s' and pick a projection using Layer/Projection..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:449
+msgid "Exit"
+msgstr "Salir"
+
+#: ../Thuban/UI/mainwindow.py:450
+msgid "The session has been modified. Do you want to save it?"
+msgstr "La sesión ha sido modificada. ¿Desea guardarla?"
+
+#: ../Thuban/UI/mainwindow.py:465
+msgid "Open Session"
+msgstr "Abrir sesión"
+
+#: ../Thuban/UI/mainwindow.py:487
+msgid "Save Session As"
+msgstr "Guardar sesión como"
+
+#: ../Thuban/UI/mainwindow.py:561
+msgid "Select one or more data files"
+msgstr "Seleccione uno o más archivos de datos"
+
+#: ../Thuban/UI/mainwindow.py:576
+msgid "Add Layer"
+msgstr "Añadir capa"
+
+#: ../Thuban/UI/mainwindow.py:577 ../Thuban/UI/mainwindow.py:602
+#: ../Thuban/UI/mainwindow.py:862
+#, python-format
+msgid "Can't open the file '%s'."
+msgstr "No se pudo abrir el fichero '%s'"
+
+#: ../Thuban/UI/mainwindow.py:589
+msgid "Select an image file"
+msgstr "Seleccionar un fichero de imagen"
+
+#: ../Thuban/UI/mainwindow.py:601
+msgid "Add Image Layer"
+msgstr "Añadir Capa de Imagen"
+
+#: ../Thuban/UI/mainwindow.py:629
+msgid "Add Layer from database"
+msgstr "Añadir Capa desde una base de datos"
+
+#: ../Thuban/UI/mainwindow.py:630
+#, python-format
+msgid "Can't open the database table '%s'"
+msgstr "No se pudo abrir la tabla '%s'"
+
+#: ../Thuban/UI/mainwindow.py:719
+#, python-format
+msgid "Copy of `%s'"
+msgstr "Copia de `%s'"
+
+#: ../Thuban/UI/mainwindow.py:749
+#, python-format
+msgid "Layer Table: %s"
+msgstr "Tabla: %s"
+
+#: ../Thuban/UI/mainwindow.py:764
+#, python-format
+msgid "Map Projection: %s"
+msgstr "Proyección del Mapa: %s"
+
+#: ../Thuban/UI/mainwindow.py:779
+#, python-format
+msgid "Layer Projection: %s"
+msgstr "Proyección de la Capa: %s"
+
+#: ../Thuban/UI/mainwindow.py:812
+msgid "Join Layer with Table"
+msgstr "Unir Capa con Tabla"
+
+#: ../Thuban/UI/mainwindow.py:834 ../Thuban/UI/mainwindow.py:1165
+msgid "Legend"
+msgstr "Leyenda"
+
+#: ../Thuban/UI/mainwindow.py:848 ../Thuban/UI/mainwindow.py:861
+msgid "Open Table"
+msgstr "Abrir Tabla"
+
+#: ../Thuban/UI/mainwindow.py:850
+msgid "DBF Files (*.dbf)"
+msgstr "Archivos DBF (*.dbf)"
+
+#: ../Thuban/UI/mainwindow.py:873
+msgid "Pick the tables to close:"
+msgstr "Elija qué tablas cerrar:"
+
+#: ../Thuban/UI/mainwindow.py:874
+msgid "Close Table"
+msgstr "Cerrar Tabla"
+
+#: ../Thuban/UI/mainwindow.py:894
+msgid "Pick the table to show:"
+msgstr "Elija qué tablas mostrar:"
+
+#: ../Thuban/UI/mainwindow.py:895
+msgid "Show Table"
+msgstr "Mostrar Tabla"
+
+#: ../Thuban/UI/mainwindow.py:906
+msgid "Join Tables"
+msgstr "Unir Tablas"
+
+#: ../Thuban/UI/mainwindow.py:929
+msgid "Pick the table to rename:"
+msgstr "Elija qué tabla renombrar:"
+
+#: ../Thuban/UI/mainwindow.py:930 ../Thuban/UI/mainwindow.py:942
+msgid "Rename Table"
+msgstr "Cambia el nombre de la Tabla"
+
+#: ../Thuban/UI/mainwindow.py:942
+#, fuzzy
+msgid "Table Title:"
+msgstr "Tabla:"
+
+#: ../Thuban/UI/mainwindow.py:991
+#, fuzzy
+msgid "Map Title:"
+msgstr "Título: "
+
+#: ../Thuban/UI/mainwindow.py:991
+#, fuzzy
+msgid "Rename Map"
+msgstr "Cambiar el nombre del mapa"
+
+#: ../Thuban/UI/mainwindow.py:1004
+#, fuzzy
+msgid "Layer Title:"
+msgstr "Tabla: %s"
+
+#: ../Thuban/UI/mainwindow.py:1004
+#, fuzzy
+msgid "Rename Layer"
+msgstr "Elimina&r Capa"
+
+#: ../Thuban/UI/mainwindow.py:1057
+#, python-format
+msgid "Thuban - %s"
+msgstr "Thuban - %s"
+
+#: ../Thuban/UI/mainwindow.py:1059
+msgid "Thuban"
+msgstr "Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1154
+msgid "&New Session"
+msgstr "&Nueva Sesión"
+
+#: ../Thuban/UI/mainwindow.py:1155
+msgid "Start a new session"
+msgstr "Iniciar nueva sesión"
+
+#: ../Thuban/UI/mainwindow.py:1156
+msgid "&Open Session..."
+msgstr "&Abrir Sesión..."
+
+#: ../Thuban/UI/mainwindow.py:1157
+msgid "Open a session file"
+msgstr "Abrir un archivo de sesión"
+
+#: ../Thuban/UI/mainwindow.py:1158
+msgid "&Save Session"
+msgstr "&Guardar Sesión"
+
+#: ../Thuban/UI/mainwindow.py:1159
+msgid "Save this session to the file it was opened from"
+msgstr "Guardar esta sesión en el archivo del que fue abierta"
+
+#: ../Thuban/UI/mainwindow.py:1160
+msgid "Save Session &As..."
+msgstr "Guardar Sesión &Como..."
+
+#: ../Thuban/UI/mainwindow.py:1161
+msgid "Save this session to a new file"
+msgstr "Guardar esta sesión en un archivo nuevo"
+
+#: ../Thuban/UI/mainwindow.py:1162
+msgid "Session &Tree"
+msgstr "A&rbol de Sesión"
+
+#: ../Thuban/UI/mainwindow.py:1164
+msgid "Toggle on/off the session tree analysis window"
+msgstr "Activar/desactivar la ventana de análisis del árbol de sesión"
+
+#: ../Thuban/UI/mainwindow.py:1167
+msgid "Toggle Legend on/off"
+msgstr "Activar/desactivar leyenda"
+
+#: ../Thuban/UI/mainwindow.py:1168
+msgid "&Database Connections..."
+msgstr "Conexiones a Bases de &Datos..."
+
+#: ../Thuban/UI/mainwindow.py:1171
+msgid "E&xit"
+msgstr "&Salir"
+
+#: ../Thuban/UI/mainwindow.py:1172
+msgid "Finish working with Thuban"
+msgstr "Termina de trabajar con Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1175
+msgid "&About..."
+msgstr "&Sobre Thuban..."
+
+#: ../Thuban/UI/mainwindow.py:1176
+msgid "Info about Thuban authors, version and modules"
+msgstr "Información sobre los autores, versión y módulos de Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1180 ../Thuban/UI/mainwindow.py:1228
+msgid "Pro&jection..."
+msgstr "Pro&yección..."
+
+#: ../Thuban/UI/mainwindow.py:1181
+msgid "Set or change the map projection"
+msgstr "Definir o cambiar la proyección del mapa"
+
+#: ../Thuban/UI/mainwindow.py:1183
+msgid "&Zoom in"
+msgstr "&Zoom+"
+
+#: ../Thuban/UI/mainwindow.py:1184
+msgid "Switch to map-mode 'zoom-in'"
+msgstr "Cambiar a modo 'zoom+'"
+
+#: ../Thuban/UI/mainwindow.py:1186
+msgid "Zoom &out"
+msgstr "Z&oom-"
+
+#: ../Thuban/UI/mainwindow.py:1187
+msgid "Switch to map-mode 'zoom-out'"
+msgstr "Cambiar a modo 'zoom-'"
+
+#: ../Thuban/UI/mainwindow.py:1189
+msgid "&Pan"
+msgstr "Des&plazar"
+
+#: ../Thuban/UI/mainwindow.py:1190
+msgid "Switch to map-mode 'pan'"
+msgstr "Cambiar a modo 'desplazar'"
+
+#: ../Thuban/UI/mainwindow.py:1192
+msgid "&Identify"
+msgstr "&Identificar"
+
+#: ../Thuban/UI/mainwindow.py:1194
+msgid "Switch to map-mode 'identify'"
+msgstr "Cambiar a modo 'identificar'"
+
+#: ../Thuban/UI/mainwindow.py:1196
+msgid "&Label"
+msgstr "&Etiqueta"
+
+#: ../Thuban/UI/mainwindow.py:1197
+msgid "Add/Remove labels"
+msgstr "Añadir/Eliminar etiquetas"
+
+#: ../Thuban/UI/mainwindow.py:1199
+msgid "&Full extent"
+msgstr "Área de &todas las capas"
+
+#: ../Thuban/UI/mainwindow.py:1200
+msgid "Zoom to the full map extent"
+msgstr "Amplía el mapa para cubrir el área de todas las capa"
+
+#: ../Thuban/UI/mainwindow.py:1202
+msgid "&Full layer extent"
+msgstr "Área de esta &Capa"
+
+#: ../Thuban/UI/mainwindow.py:1203
+msgid "Zoom to the full layer extent"
+msgstr "Amplía el mapa para cubrir el área de la capa actual"
+
+#: ../Thuban/UI/mainwindow.py:1205
+msgid "&Full selection extent"
+msgstr "Cobertura de la &Selección"
+
+#: ../Thuban/UI/mainwindow.py:1207
+msgid "Zoom to the full selection extent"
+msgstr "Amplía el mapa para cubrir el área de la selección"
+
+#: ../Thuban/UI/mainwindow.py:1209
+msgid "E&xport"
+msgstr "E&xportar"
+
+#: ../Thuban/UI/mainwindow.py:1210
+msgid "Export the map to file"
+msgstr "Exportar el mapa a un archivo"
+
+#: ../Thuban/UI/mainwindow.py:1211
+msgid "Prin&t"
+msgstr "Imp&rimir"
+
+#: ../Thuban/UI/mainwindow.py:1212
+msgid "Print the map"
+msgstr "Imprimir el mapa"
+
+#: ../Thuban/UI/mainwindow.py:1213 ../Thuban/UI/mainwindow.py:1299
+msgid "&Rename..."
+msgstr "Cambiar nomb&re..."
+
+#: ../Thuban/UI/mainwindow.py:1214
+msgid "Rename the map"
+msgstr "Cambiar el nombre del mapa"
+
+#: ../Thuban/UI/mainwindow.py:1215
+msgid "&Add Layer..."
+msgstr "&Añadir Capa..."
+
+#: ../Thuban/UI/mainwindow.py:1216
+msgid "Add a new layer to the map"
+msgstr "Añadir una capa al mapa"
+
+#: ../Thuban/UI/mainwindow.py:1217
+msgid "&Add Image Layer..."
+msgstr "Añadir Capa I&magen..."
+
+#: ../Thuban/UI/mainwindow.py:1218
+msgid "Add a new image layer to the map"
+msgstr "Añadir una capa imagen al mapa"
+
+#: ../Thuban/UI/mainwindow.py:1220
+msgid "Add &Database Layer..."
+msgstr "Añadir Capa de Base de &Datos..."
+
+#: ../Thuban/UI/mainwindow.py:1221
+msgid "Add a new database layer to active map"
+msgstr "Añadir una capa de base de datos al mapa activo"
+
+#: ../Thuban/UI/mainwindow.py:1223
+msgid "&Remove Layer"
+msgstr "Elimina&r Capa"
+
+#: ../Thuban/UI/mainwindow.py:1224
+msgid "Remove selected layer"
+msgstr "Eliminar la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1230
+msgid "Specify projection for selected layer"
+msgstr "Especificar la proyección de la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1231
+msgid "&Duplicate"
+msgstr "&Duplicar"
+
+#: ../Thuban/UI/mainwindow.py:1232
+msgid "Duplicate selected layer"
+msgstr "Duplicar la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1234
+msgid "Re&name ..."
+msgstr "Cambiar nomb&re..."
+
+#: ../Thuban/UI/mainwindow.py:1235
+msgid "Rename selected layer"
+msgstr "Cambia el nombre de la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1237
+msgid "&Raise"
+msgstr "&Elevar"
+
+#: ../Thuban/UI/mainwindow.py:1238
+msgid "Raise selected layer"
+msgstr "Elevar de nivel la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1240
+msgid "&Lower"
+msgstr "&Bajar"
+
+#: ../Thuban/UI/mainwindow.py:1241
+msgid "Lower selected layer"
+msgstr "Bajar de nivel la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1243
+msgid "&Show"
+msgstr "Mo&strar"
+
+#: ../Thuban/UI/mainwindow.py:1244
+msgid "Make selected layer visible"
+msgstr "Hacer visible la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1246
+msgid "&Hide"
+msgstr "&Ocultar"
+
+#: ../Thuban/UI/mainwindow.py:1247
+msgid "Make selected layer unvisible"
+msgstr "Ocultar la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1249
+msgid "Show Ta&ble"
+msgstr "Mostrar Ta&bla"
+
+#: ../Thuban/UI/mainwindow.py:1250
+msgid "Show the selected layer's table"
+msgstr "Mostrar la tabla de atributos de la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1252
+msgid "&Properties..."
+msgstr "&Propiedades..."
+
+#: ../Thuban/UI/mainwindow.py:1254
+msgid "Edit the properties of the selected layer"
+msgstr "Editar las propiedades de la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1255
+msgid "&Join Table..."
+msgstr "&Unir Tabla..."
+
+#: ../Thuban/UI/mainwindow.py:1257
+msgid "Join and attach a table to the selected layer"
+msgstr "Unir y agregar una tabla a la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1260
+msgid "&Top"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1261
+#, fuzzy
+msgid "Put selected layer to the top"
+msgstr "Duplicar la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1263
+#, fuzzy
+msgid "&Bottom"
+msgstr "Capa Inferior"
+
+#: ../Thuban/UI/mainwindow.py:1264
+#, fuzzy
+msgid "Put selected layer to the bottom"
+msgstr "Duplicar la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1266
+#, fuzzy
+msgid "&Visible"
+msgstr "Visible"
+
+#: ../Thuban/UI/mainwindow.py:1268
+#, fuzzy
+msgid "Toggle visibility of selected layer"
+msgstr "Elevar de nivel la capa seleccionada"
+
+#: ../Thuban/UI/mainwindow.py:1285
+msgid "&Unjoin Table..."
+msgstr "&Desunir Tabla..."
+
+#: ../Thuban/UI/mainwindow.py:1287
+msgid "Undo the last join operation"
+msgstr "Deshacer la última unión"
+
+#: ../Thuban/UI/mainwindow.py:1294
+msgid "&Open..."
+msgstr "&Abrir..."
+
+#: ../Thuban/UI/mainwindow.py:1295
+msgid "Open a DBF-table from a file"
+msgstr "Abrir un archivo de tabla DBF"
+
+#: ../Thuban/UI/mainwindow.py:1296
+msgid "&Close..."
+msgstr "&Cerrar..."
+
+#: ../Thuban/UI/mainwindow.py:1298
+msgid "Close one or more tables from a list"
+msgstr "Cerrar una o más tablas a partir de una lista"
+
+#: ../Thuban/UI/mainwindow.py:1301
+msgid "Rename one or more tables"
+msgstr "Cambiar el nombre de una o más tablas"
+
+#: ../Thuban/UI/mainwindow.py:1302
+msgid "&Show..."
+msgstr "Mo&strar..."
+
+#: ../Thuban/UI/mainwindow.py:1304
+msgid "Show one or more tables in a dialog"
+msgstr "Mostrar una o más tablas"
+
+#: ../Thuban/UI/mainwindow.py:1305
+msgid "&Join..."
+msgstr "&Unir..."
+
+#: ../Thuban/UI/mainwindow.py:1307
+msgid "Join two tables creating a new one"
+msgstr "Unir dos tablas en una tabla nueva"
+
+#: ../Thuban/UI/mainwindow.py:1331
+msgid "&File"
+msgstr "&Archivo"
+
+#: ../Thuban/UI/mainwindow.py:1337
+msgid "&Map"
+msgstr "&Mapa"
+
+#: ../Thuban/UI/mainwindow.py:1338
+msgid "&Layer"
+msgstr "&Capa"
+
+#: ../Thuban/UI/mainwindow.py:1352
+msgid "&Table"
+msgstr "&Tabla"
+
+#: ../Thuban/UI/mainwindow.py:1358
+msgid "&Help"
+msgstr "A&yuda"
+
+#: ../Thuban/UI/menu.py:90
+#, python-format
+msgid "Submenu %s doesn't exist"
+msgstr "El submenu %s no existe"
+
+#: ../Thuban/UI/projdialog.py:62 ../Thuban/UI/projdialog.py:776
+msgid "Transverse Mercator"
+msgstr "Mercator Transversa"
+
+#: ../Thuban/UI/projdialog.py:63 ../Thuban/UI/projdialog.py:842
+msgid "Universal Transverse Mercator"
+msgstr "Mercator Transversa Universal (UTM)"
+
+#: ../Thuban/UI/projdialog.py:64 ../Thuban/UI/projdialog.py:918
+msgid "Lambert Conic Conformal"
+msgstr "Lambert Cónica Conforme"
+
+#: ../Thuban/UI/projdialog.py:65 ../Thuban/UI/projdialog.py:66
+#: ../Thuban/UI/projdialog.py:968
+msgid "Geographic"
+msgstr "Geográfica"
+
+#: ../Thuban/UI/projdialog.py:110
+msgid "Import..."
+msgstr "Importar..."
+
+#: ../Thuban/UI/projdialog.py:113
+msgid "Export..."
+msgstr "Exportar..."
+
+#: ../Thuban/UI/projdialog.py:122
+msgid "Show EPSG:"
+msgstr "Mostrar EPSG:"
+
+#: ../Thuban/UI/projdialog.py:124
+msgid "Normal"
+msgstr "Normal"
+
+#: ../Thuban/UI/projdialog.py:127
+msgid "Deprecated"
+msgstr "Descontinuado"
+
+#: ../Thuban/UI/projdialog.py:138
+msgid "Edit"
+msgstr "Editar"
+
+#: ../Thuban/UI/projdialog.py:148
+msgid "Name:"
+msgstr "Nombre:"
+
+#: ../Thuban/UI/projdialog.py:156
+msgid "Projection:"
+msgstr "Proyección:"
+
+#: ../Thuban/UI/projdialog.py:167 ../Thuban/UI/projdialog.py:648
+msgid "<Unknown>"
+msgstr "<Desconocido>"
+
+#: ../Thuban/UI/projdialog.py:183
+msgid "New"
+msgstr "Nueva"
+
+#: ../Thuban/UI/projdialog.py:186
+msgid "Add to List"
+msgstr "Añadir a disponibles"
+
+#: ../Thuban/UI/projdialog.py:190
+msgid "Update"
+msgstr "Actualizar"
+
+#: ../Thuban/UI/projdialog.py:295
+#, python-format
+msgid ""
+"Warnings when reading \"%s\":\n"
+"\n"
+"%s"
+msgstr ""
+"Se detectó alertas en la lectura de \"%s\":\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/projdialog.py:306
+msgid "Import"
+msgstr "Importar"
+
+#: ../Thuban/UI/projdialog.py:319 ../Thuban/UI/projdialog.py:617
+msgid "Warnings"
+msgstr "Alertas"
+
+#: ../Thuban/UI/projdialog.py:337 ../Thuban/UI/tableview.py:386
+msgid "Export"
+msgstr "Exportar"
+
+#: ../Thuban/UI/projdialog.py:389
+msgid "The following error occured:\n"
+msgstr "Ocurrió el error siguiente:\n"
+
+#: ../Thuban/UI/projdialog.py:391
+msgid "Error"
+msgstr "Error"
+
+#: ../Thuban/UI/projdialog.py:460
+msgid "No Projections selected"
+msgstr "No se selccionó Proyecciones"
+
+#: ../Thuban/UI/projdialog.py:470
+#, python-format
+msgid "Source of Projection: %s"
+msgstr "Fuente de la Proyección: %s"
+
+#: ../Thuban/UI/projdialog.py:502
+msgid "Multiple Projections selected"
+msgstr "Se seleccionó Proyecciones múltiples"
+
+#: ../Thuban/UI/projdialog.py:649
+msgid "Airy"
+msgstr "Airy"
+
+#: ../Thuban/UI/projdialog.py:650
+msgid "Bessel 1841"
+msgstr "Bessel 1841"
+
+#: ../Thuban/UI/projdialog.py:651
+msgid "Clarke 1866"
+msgstr "Clarke 1866"
+
+#: ../Thuban/UI/projdialog.py:652
+msgid "Clarke 1880"
+msgstr "Clarke 1880"
+
+#: ../Thuban/UI/projdialog.py:653
+msgid "GRS 1980 (IUGG, 1980)"
+msgstr "GRS 1980 (IUGG, 1980)"
+
+#: ../Thuban/UI/projdialog.py:654
+msgid "International 1909 (Hayford)"
+msgstr "Internacional 1909 (Hayford)"
+
+#: ../Thuban/UI/projdialog.py:655
+msgid "WGS 84"
+msgstr "WGS 84"
+
+#: ../Thuban/UI/projdialog.py:667
+msgid "Ellipsoid:"
+msgstr "Elipsoide:"
+
+#: ../Thuban/UI/projdialog.py:716
+msgid ""
+"Thuban does not know the parameters\n"
+"for the current projection and cannot\n"
+"display a configuration panel.\n"
+"\n"
+"The unidentified set of parameters is:\n"
+"\n"
+msgstr ""
+"Thuban desconoce los parámetros \n"
+"de la proyección actual y no puede \n"
+"mostrar un panel de configuración.\n"
+"\n"
+"El juego de parámetros desconocido es:\n"
+"\n"
+
+#: ../Thuban/UI/projdialog.py:762
+msgid "Latitude:"
+msgstr "Latitud:"
+
+#: ../Thuban/UI/projdialog.py:764
+msgid "Longitude:"
+msgstr "Longitud:"
+
+#: ../Thuban/UI/projdialog.py:766 ../Thuban/UI/projdialog.py:910
+msgid "False Easting:"
+msgstr "Falso Este:"
+
+#: ../Thuban/UI/projdialog.py:768 ../Thuban/UI/projdialog.py:912
+msgid "False Northing:"
+msgstr "Falso Norte:"
+
+#: ../Thuban/UI/projdialog.py:770
+msgid "Scale Factor:"
+msgstr "Factor de Escala:"
+
+#: ../Thuban/UI/projdialog.py:821
+msgid "Propose"
+msgstr "Proponer"
+
+#: ../Thuban/UI/projdialog.py:823
+msgid "Southern Hemisphere"
+msgstr "Hemisferio Sur"
+
+#: ../Thuban/UI/projdialog.py:833
+msgid "Zone:"
+msgstr "Zona:"
+
+#: ../Thuban/UI/projdialog.py:870
+msgid "Can not propose: No bounding box found."
+msgstr "No se puede proponer: No hay una caja de contorno.XX"
+
+#: ../Thuban/UI/projdialog.py:871 ../Thuban/UI/projdialog.py:1008
+msgid "Projection: Propose UTM Zone"
+msgstr "Proyección: Proponer Zona UTM"
+
+#: ../Thuban/UI/projdialog.py:901
+msgid "Latitude of first standard parallel:"
+msgstr "Latitud del primer paralelo estándar"
+
+#: ../Thuban/UI/projdialog.py:904
+msgid "Latitude of second standard parallel:"
+msgstr "Latitud del segundo paralelo estándar"
+
+#: ../Thuban/UI/projdialog.py:906
+msgid "Central Meridian:"
+msgstr "Meridiano Central:"
+
+#: ../Thuban/UI/projdialog.py:908
+msgid "Latitude of origin:"
+msgstr "Latitud del orígen:"
+
+#: ../Thuban/UI/projdialog.py:958
+msgid "Degrees"
+msgstr "Grados"
+
+#: ../Thuban/UI/projdialog.py:959
+msgid "Radians"
+msgstr "Radianes"
+
+#: ../Thuban/UI/projdialog.py:992
+msgid "Source Data is in: "
+msgstr "Los datos originales están en: "
+
+#: ../Thuban/UI/projdialog.py:1021
+msgid "The current map extent center lies in UTM Zone"
+msgstr "El centro del mapa actual está en zona UTM"
+
+#: ../Thuban/UI/projdialog.py:1031
+msgid "Take"
+msgstr "Tomar"
+
+#: ../Thuban/UI/projlist.py:51
+msgid "Available Projections"
+msgstr "Proyecciones disponibles"
+
+#: ../Thuban/UI/projlist.py:112
+msgid "<None>"
+msgstr "<Ninguno>"
+
+#: ../Thuban/UI/projlist.py:117
+#, python-format
+msgid "%s (current)"
+msgstr "%s (actual)"
+
+#: ../Thuban/UI/rasterlayerproperties.py:41
+msgid "GDAL image information unavailable. See About box for details."
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:49
+#, fuzzy
+msgid "Extent (lat-lon): None"
+msgstr "Cobertura (lat-lon):"
+
+#: ../Thuban/UI/rasterlayerproperties.py:56
+#, fuzzy
+msgid "Image Properties"
+msgstr "Propiedades de la Capa"
+
+#: ../Thuban/UI/rasterlayerproperties.py:61
+#, python-format
+msgid "Source: %s"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:71
+#, fuzzy, python-format
+msgid "Driver: %s"
+msgstr "Campo: %s"
+
+#: ../Thuban/UI/rasterlayerproperties.py:74
+#, python-format
+msgid "Size: %ix%i"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:77
+#, fuzzy, python-format
+msgid "Number of Bands: %i"
+msgstr "Número de Grupos:"
+
+#: ../Thuban/UI/rasterlayerproperties.py:93
+msgid "Mask Type"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:99
+msgid "Opacity:"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:381
+msgid "Replace Selection"
+msgstr "Reemplazar selección"
+
+#: ../Thuban/UI/tableview.py:382
+msgid "Refine Selection"
+msgstr "Refinar la selección"
+
+#: ../Thuban/UI/tableview.py:383
+msgid "Add to Selection"
+msgstr "Añadir a la selección"
+
+#: ../Thuban/UI/tableview.py:385
+msgid "Query"
+msgstr "Seleccionar"
+
+#: ../Thuban/UI/tableview.py:387
+msgid "Export Selection"
+msgstr "Exportar la selección"
+
+#: ../Thuban/UI/tableview.py:413
+msgid "Selection"
+msgstr "Selección"
+
+#: ../Thuban/UI/tableview.py:455
+#, python-format
+msgid "%i rows (%i selected), %i columns"
+msgstr "%i líneas (%i seleccionadas), %i columnas"
+
+#: ../Thuban/UI/tableview.py:535
+msgid "Export Table To"
+msgstr "Exportar Tabla"
+
+#: ../Thuban/UI/tableview.py:536
+msgid "DBF Files (*.dbf)|*.dbf|"
+msgstr "Archivos DBF (*.dbf)|*.dbf|"
+
+#: ../Thuban/UI/tableview.py:537
+msgid "CSV Files (*.csv)|*.csv|"
+msgstr "Archivos CSV (*.csv)|*.csv|"
+
+#: ../Thuban/UI/tableview.py:538
+msgid "All Files (*.*)|*.*"
+msgstr "Todos los archivos (*.*)|*.*"
+
+#: ../Thuban/UI/tree.py:226
+msgid "Session"
+msgstr "Sesión"
+
+#: ../Thuban/UI/view.py:285
+msgid "Export Map"
+msgstr "Exportar Mapa"
+
+#~ msgid "Type: %s"
+#~ msgstr "Tipo: %s"
+
+#~ msgid "Projection: UTM Parameters"
+#~ msgstr "Proyección: Parámetros UTM"
+
+#~ msgid "UTM Zone"
+#~ msgstr "Zona UTM"
+
+#~ msgid "Ellipsoid"
+#~ msgstr "Elipsoide"

Added: packages/thuban/branches/upstream/current/po/fr.po
===================================================================
--- packages/thuban/branches/upstream/current/po/fr.po	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/po/fr.po	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1856 @@
+# French translation for Thuban
+# Traduction française de Thuban
+# Copyright (C) 2003
+# This file is distributed under the same license as the Thuban package.
+# Ce fichier est distribué sous la même licence que Thuban
+# Daniel Calvelo Aros <dcalvelo at minag.gob.pe>, 2003
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Thuban 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-03-13 20:15+0000\n"
+"PO-Revision-Date: 2003-12-16 15:12-0500\n"
+"Last-Translator: Daniel Calvelo Aros <dcalvelo at minag.gob.pe>\n"
+"Language-Team: Thuban developers <thuban at intevation.de>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../Thuban/version.py:189
+#, python-format
+msgid "%s %s < %s"
+msgstr "%s %s < %s"
+
+#: ../Thuban/version.py:195
+#, python-format
+msgid "Thuban was compiled with wx %(wxproj-wx)s but wxPython is %(wxPython)s"
+msgstr ""
+
+#: ../Thuban/Lib/connector.py:65
+#, python-format
+msgid "no receivers for channel %s of %s"
+msgstr "pas de récepteur pour le canal %s de %s"
+
+#: ../Thuban/Lib/connector.py:70
+#, python-format
+msgid "receiver %s%s is not connected to channel %s of %s"
+msgstr "le récepteur %s%s n'est pas connecté au canal %s de %s"
+
+#: ../Thuban/Lib/connector.py:94
+#, python-format
+msgid "Warning: %s.%s: %s%s\n"
+msgstr "Alerte: %s.%s: %s%s\n"
+
+#: ../Thuban/Lib/connector.py:118
+#, python-format
+msgid "\tmethod %s of %s"
+msgstr "\tméthode %s de %s"
+
+#: ../Thuban/Lib/fileutil.py:87 ../Thuban/Lib/fileutil.py:141
+msgid "first argument must be an absolute filename"
+msgstr "le premier argument doit être un chemin d'accès absolu à un fichier"
+
+#: ../Thuban/Lib/fileutil.py:138
+msgid "Both parameters must have a drive letter"
+msgstr "Les deux paramètres doivent avoir une lettre d'unité"
+
+#: ../Thuban/Lib/fileutil.py:198
+msgid "No implementation of get_application_dir available for platform"
+msgstr "Cette plateforme ne définit pas la fonction get_application_dir"
+
+#: ../Thuban/Lib/fileutil.py:208
+msgid "No implementation of relative_filename available for platform"
+msgstr "Cette plateforme ne définit pas la fonction relative_filename"
+
+#: ../Thuban/Model/classgen.py:338
+msgid "invalid index"
+msgstr "indice non valable"
+
+#: ../Thuban/Model/classification.py:309 ../Thuban/UI/classifier.py:758
+msgid "None"
+msgstr "Néant"
+
+#: ../Thuban/Model/classification.py:325
+msgid "Line Color"
+msgstr "Couleur de Trait"
+
+#: ../Thuban/Model/classification.py:327
+#, python-format
+msgid "Line Width: %s"
+msgstr "Largeur de Trait: %s"
+
+#: ../Thuban/Model/classification.py:333
+#, fuzzy, python-format
+msgid "Size: %s"
+msgstr "Champ: %s"
+
+#: ../Thuban/Model/classification.py:336
+msgid "Fill"
+msgstr "Remplir"
+
+#: ../Thuban/Model/classification.py:342 ../Thuban/UI/classifier.py:841
+msgid "Classification"
+msgstr "Classification"
+
+#: ../Thuban/Model/classification.py:436
+msgid "lineWidth < 1"
+msgstr "largeur < 1"
+
+#: ../Thuban/Model/classification.py:451
+msgid "size < 1"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:656 ../Thuban/UI/classifier.py:528
+msgid "DEFAULT"
+msgstr "DÉFAUT"
+
+#: ../Thuban/Model/data.py:316
+msgid "Table not compatible with shapestore."
+msgstr "La Table n'est pas compatible avec le dépôt de données"
+
+#: ../Thuban/Model/extension.py:90
+#, python-format
+msgid "Extension: %s"
+msgstr "Extension: %s"
+
+#: ../Thuban/Model/label.py:91
+#, fuzzy, python-format
+msgid "Number of labels: %d"
+msgstr "Nombre de Classes:"
+
+#: ../Thuban/Model/label.py:92
+#, fuzzy, python-format
+msgid "Label Layer: %s"
+msgstr "Table: %s"
+
+#: ../Thuban/Model/layer.py:298 ../Thuban/Model/layer.py:566
+#: ../Thuban/Model/session.py:432
+#, python-format
+msgid "Filename: %s"
+msgstr "Nom de Fichier: %s"
+
+#: ../Thuban/Model/layer.py:301 ../Thuban/Model/layer.py:569
+msgid "Shown"
+msgstr "Affiché"
+
+#: ../Thuban/Model/layer.py:303 ../Thuban/Model/layer.py:571
+msgid "Hidden"
+msgstr "Occulte"
+
+#: ../Thuban/Model/layer.py:304
+#, python-format
+msgid "Shapes: %d"
+msgstr "Éléments: %d"
+
+#: ../Thuban/Model/layer.py:308 ../Thuban/Model/layer.py:575
+#: ../Thuban/Model/map.py:287 ../Thuban/UI/rasterlayerproperties.py:51
+#, python-format
+msgid "Extent (lat-lon): (%g, %g, %g, %g)"
+msgstr "Extension (lat-lon): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/layer.py:310 ../Thuban/Model/layer.py:577
+msgid "Extent (lat-lon):"
+msgstr "Extension (lat-lon):"
+
+#: ../Thuban/Model/layer.py:311
+#, python-format
+msgid "Shapetype: %s"
+msgstr "Type: %s"
+
+#: ../Thuban/Model/layer.py:314 ../Thuban/Model/layer.py:580
+#: ../Thuban/Model/map.py:292
+msgid "Projection"
+msgstr "Projection"
+
+#: ../Thuban/Model/layer.py:319 ../Thuban/Model/layer.py:583
+#, python-format
+msgid "Layer '%s'"
+msgstr "Couche '%s'"
+
+#: ../Thuban/Model/load.py:78
+#, python-format
+msgid "Invalid hexadecimal color specification %s"
+msgstr "Spécification de couleur héxadécimale incorrecte %s"
+
+#: ../Thuban/Model/load.py:81
+#, python-format
+msgid "Invalid color specification %s"
+msgstr "Spécification de couleur incorrecte %s"
+
+#: ../Thuban/Model/load.py:544
+msgid "xml field type differs from database!"
+msgstr "Le type de champ xml est différent de celui de la base de données!"
+
+#: ../Thuban/Model/load.py:609
+msgid "Classification range is not a number!"
+msgstr "Le rang de classification n'est pas un nombre!"
+
+#: ../Thuban/Model/map.py:53
+msgid "Labels"
+msgstr "Étiquettes"
+
+#: ../Thuban/Model/map.py:290
+#, python-format
+msgid "Extent (projected): (%g, %g, %g, %g)"
+msgstr "Extension (projetée): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/map.py:301
+#, python-format
+msgid "Map: %s"
+msgstr "Carte: %s"
+
+#: ../Thuban/Model/proj.py:84 ../Thuban/Model/resource.py:179
+msgid "Unknown"
+msgstr "Inconnu"
+
+#: ../Thuban/Model/resource.py:46
+#, python-format
+msgid ""
+"No GDAL support because module '%s' cannot be imported. Python exception: '%"
+"s'"
+msgstr ""
+"GDAL n'est pas disponible parce que le module '%s' n'a pas pu être importé. "
+"L'exception déclenchée par Python est: '%s'"
+
+#: ../Thuban/Model/resource.py:135 ../Thuban/Model/resource.py:155
+#, python-format
+msgid "Could not read \"%s\": %s"
+msgstr "Impossible de lire \"%s\": %s"
+
+#: ../Thuban/Model/resource.py:187
+#, python-format
+msgid "Error in projection \"%s\": %s"
+msgstr "Erreur dans la Projection \"%s\": %s"
+
+#: ../Thuban/Model/save.py:352
+msgid "Unsupported group type in classification"
+msgstr "Type de groupe non géré par la classification"
+
+#: ../Thuban/Model/session.py:430
+msgid "Filename:"
+msgstr "Nom de fichier:"
+
+#: ../Thuban/Model/session.py:435
+msgid "Modified"
+msgstr "Modifié"
+
+#: ../Thuban/Model/session.py:437
+msgid "Unmodified"
+msgstr "Non modifié"
+
+#: ../Thuban/Model/session.py:442
+#, python-format
+msgid "Session: %s"
+msgstr "Session: %s"
+
+#: ../Thuban/Model/session.py:448
+msgid "unnamed session"
+msgstr "session sans nom"
+
+#: ../Thuban/Model/session.py:450
+msgid "unnamed map"
+msgstr "carte sans nom"
+
+#: ../Thuban/UI/about.py:28
+msgid "About Thuban"
+msgstr "A props de Thuban"
+
+#: ../Thuban/UI/about.py:47
+msgid "French"
+msgstr "Français"
+
+#: ../Thuban/UI/about.py:48
+msgid "German"
+msgstr "Allemand"
+
+#: ../Thuban/UI/about.py:50
+msgid "Hungarian"
+msgstr ""
+
+#: ../Thuban/UI/about.py:51
+msgid "Italian"
+msgstr "Italien"
+
+#: ../Thuban/UI/about.py:52
+msgid "Portuguese (Brazilian)"
+msgstr ""
+
+#: ../Thuban/UI/about.py:53
+msgid "Russian"
+msgstr "Russe"
+
+#: ../Thuban/UI/about.py:54
+msgid "Spanish"
+msgstr "Espagnol"
+
+#: ../Thuban/UI/about.py:63 ../Thuban/UI/about.py:65 ../Thuban/UI/about.py:67
+msgid "- not available"
+msgstr "- non disponible"
+
+#: ../Thuban/UI/about.py:72
+msgid "Currently using:\n"
+msgstr "Utilise actuellement:\n"
+
+#: ../Thuban/UI/about.py:78
+#, python-format
+msgid "\tInternal encoding: %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:84
+msgid "Compiled for:\n"
+msgstr "Compilé pour:\n"
+
+#: ../Thuban/UI/about.py:90
+#, fuzzy
+msgid "Extensions:\n"
+msgstr "Extension: %s"
+
+#: ../Thuban/UI/about.py:95 ../Thuban/UI/about.py:144
+msgid "\tNone registered.\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:98
+msgid "Maintainers:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:103
+msgid "Lead Developer:\n"
+msgstr "Développeur Principal:\n"
+
+#: ../Thuban/UI/about.py:106
+msgid "Developers:\n"
+msgstr "Développeurs:\n"
+
+#: ../Thuban/UI/about.py:111
+msgid "Translators:\n"
+msgstr "Traducteurs:\n"
+
+#: ../Thuban/UI/about.py:116
+msgid "Other Contributors:\n"
+msgstr "Autres Collaborateurs:\n"
+
+#: ../Thuban/UI/about.py:122
+#, fuzzy
+msgid ""
+"Questions and comments can be sent to the following addresses:\n"
+"\tGeneral list (public):\n"
+"\t\t<thuban-list at intevation.de>\n"
+"\tDevelopers list (public):\n"
+"\t\t<thuban-devel at intevation.de>\n"
+"\tThuban team at Intevation:\n"
+"\t\t<thuban at intevation.de>\n"
+msgstr ""
+"Vos questions et commentaires peuvent être adressés à:\n"
+"\tDéveloppement de Thuban:\n"
+"\t\t<thuban at intevation.de>\n"
+"\tListe de discussion sur Thuban:\n"
+"\t\t<thuban-list at intevation.de>"
+
+#: ../Thuban/UI/about.py:130
+msgid ""
+"Details on the registered extensions:\n"
+"\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:135
+#, python-format
+msgid "Copyright %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:136
+msgid "Authors:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:149
+msgid ""
+"Thuban is a program for exploring geographic data.\n"
+"\n"
+msgstr ""
+"Thuban est un logiciel pour l'exploration de données géographiques\n"
+"\n"
+
+#: ../Thuban/UI/about.py:151
+msgid "Thuban is licensed under the GNU GPL"
+msgstr "Thuban est distribué sous la licence GPL de GNU"
+
+#: ../Thuban/UI/about.py:160 ../Thuban/UI/classgen.py:91
+#: ../Thuban/UI/dbdialog.py:276 ../Thuban/UI/dock.py:371
+#: ../Thuban/UI/join.py:66 ../Thuban/UI/layerproperties.py:82
+#: ../Thuban/UI/projdialog.py:209 ../Thuban/UI/tableview.py:388
+msgid "Close"
+msgstr "Fermer"
+
+#: ../Thuban/UI/altpathdialog.py:24
+#, fuzzy, python-format
+msgid "Select an alternative data file for %s"
+msgstr "Choisir un ou plusieurs fichiers de données"
+
+#: ../Thuban/UI/altpathdialog.py:31 ../Thuban/UI/mainwindow.py:563
+msgid "Shapefiles (*.shp)"
+msgstr "Shapefiles (*.shp)"
+
+#: ../Thuban/UI/altpathdialog.py:32 ../Thuban/UI/mainwindow.py:564
+#: ../Thuban/UI/mainwindow.py:852
+msgid "All Files (*.*)"
+msgstr "Tous (*.*)"
+
+#: ../Thuban/UI/altpathdialog.py:47
+#, python-format
+msgid ""
+"Found the following as an alternative for %s.\n"
+"%s\n"
+"\n"
+" Please confirm with Yes or select alternative with No."
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:49
+msgid "Alternative Path"
+msgstr ""
+
+#: ../Thuban/UI/application.py:110 ../Thuban/UI/application.py:122
+msgid "Cannot import the thubanstart module\n"
+msgstr "N'a pu importer le module initial thubanstart\n"
+
+#: ../Thuban/UI/application.py:115
+msgid "No thubanstart module available\n"
+msgstr "N'a pu trouver le module initial thubanstart\n"
+
+#: ../Thuban/UI/application.py:126
+msgid "No ~/.thuban directory\n"
+msgstr "Le répertoire ~/.thuban n'existe pas\n"
+
+#: ../Thuban/UI/application.py:166
+msgid ""
+"This is the wxPython-based Graphical User Interface for exploring geographic "
+"data"
+msgstr ""
+"Voici l'interface graphique pour l'exploration de données géographiques "
+"basée sur wxPython"
+
+#: ../Thuban/UI/application.py:254
+msgid ""
+"The current session contains Image layers,\n"
+"but the GDAL library is not available to draw them."
+msgstr ""
+"La session actuelle contient des couches image,\n"
+"mais la bibliothèque GDAL n'est pas disponible pour les utiliser."
+
+#: ../Thuban/UI/application.py:259
+msgid "Library not available"
+msgstr "Bibliothèque non disponible"
+
+#: ../Thuban/UI/application.py:268 ../Thuban/UI/mainwindow.py:476
+msgid "DB Connection Parameters"
+msgstr "Paramètres de Connexion à la Base de Données"
+
+#: ../Thuban/UI/application.py:364
+#, python-format
+msgid ""
+"An unhandled exception occurred:\n"
+"%s\n"
+"(please report to http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+msgstr ""
+"Une exception non gérée a été déclenchée:\n"
+"%s\n"
+"(veuillez faire un rapport à l'adresse http://thuban.intevation.org/"
+"bugtracker.html)\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/classgen.py:43
+msgid "Uniform Distribution"
+msgstr "Distribution Uniforme"
+
+#: ../Thuban/UI/classgen.py:44
+msgid "Unique Values"
+msgstr "Valeurs Uniques"
+
+#: ../Thuban/UI/classgen.py:45
+msgid "Quantiles from Table"
+msgstr "Quantiles à partir de la Table"
+
+#: ../Thuban/UI/classgen.py:47
+msgid "Custom Ramp"
+msgstr "Rampe Personnalisée"
+
+#: ../Thuban/UI/classgen.py:48
+msgid "Grey Ramp"
+msgstr "Rampe Grise"
+
+#: ../Thuban/UI/classgen.py:49
+msgid "Red Ramp"
+msgstr "Rampe Rouge"
+
+#: ../Thuban/UI/classgen.py:50
+msgid "Green Ramp"
+msgstr "Rampe Verte"
+
+#: ../Thuban/UI/classgen.py:51
+msgid "Blue Ramp"
+msgstr "Rampe Bleue"
+
+#: ../Thuban/UI/classgen.py:52
+msgid "Green-to-Red Ramp"
+msgstr "Rampe du Vert au Rouge"
+
+#: ../Thuban/UI/classgen.py:53
+msgid "Hot-to-Cold Ramp"
+msgstr "Rampe Chaud-et-Froid"
+
+#: ../Thuban/UI/classgen.py:69
+msgid "Generate Classification"
+msgstr "Générer la Classification"
+
+#: ../Thuban/UI/classgen.py:90
+msgid "Generate"
+msgstr "Générer"
+
+#: ../Thuban/UI/classgen.py:119
+#, python-format
+msgid "Field: %s"
+msgstr "Champ: %s"
+
+#: ../Thuban/UI/classgen.py:123 ../Thuban/UI/classifier.py:976
+#, python-format
+msgid "Data Type: %s"
+msgstr "Type de Donnée: %s"
+
+#: ../Thuban/UI/classgen.py:127
+msgid "Generate:"
+msgstr "Générer:"
+
+#: ../Thuban/UI/classgen.py:137
+msgid "Color Scheme:"
+msgstr "Couleurs:"
+
+#: ../Thuban/UI/classgen.py:161
+msgid "Fix Border Color"
+msgstr "Couleur de Trait fixe"
+
+#: ../Thuban/UI/classgen.py:168 ../Thuban/UI/classgen.py:936
+#: ../Thuban/UI/classgen.py:967
+msgid "Change"
+msgstr "Changer"
+
+#: ../Thuban/UI/classgen.py:274
+msgid ""
+"Based on the data from the table and the input\n"
+"values, the exact quantiles could not be generated.\n"
+"\n"
+"Accept a close estimate?"
+msgstr ""
+"À partir des données de la table et les valeurs indiquées,\n"
+"des quantiles exacts n'ont pas pu être générés.\n"
+"\n"
+"Acceptez-vous une approximation?"
+
+#: ../Thuban/UI/classgen.py:277
+msgid "Problem with Quantiles"
+msgstr "Problème de Quantiles"
+
+#: ../Thuban/UI/classgen.py:370
+msgid "Min:"
+msgstr "Min:"
+
+#: ../Thuban/UI/classgen.py:375
+msgid "Max:"
+msgstr "Max:"
+
+#: ../Thuban/UI/classgen.py:380 ../Thuban/UI/classgen.py:633
+msgid "Retrieve From Table"
+msgstr "Extraire de la Table"
+
+#: ../Thuban/UI/classgen.py:390
+msgid "Number of Groups:"
+msgstr "Nombre de Groupes:"
+
+#: ../Thuban/UI/classgen.py:397
+msgid "Stepping:"
+msgstr "Intervale:"
+
+#: ../Thuban/UI/classgen.py:647
+#, fuzzy
+msgid "Available"
+msgstr "- non disponible"
+
+#: ../Thuban/UI/classgen.py:652 ../Thuban/UI/classgen.py:692
+msgid "Sort"
+msgstr "Trier"
+
+#: ../Thuban/UI/classgen.py:655 ../Thuban/UI/classgen.py:695
+msgid "Reverse"
+msgstr "Inverser"
+
+#: ../Thuban/UI/classgen.py:687
+#, fuzzy
+msgid "Use"
+msgstr "Utilisateur:"
+
+#: ../Thuban/UI/classgen.py:832
+msgid "Retrieve from Table"
+msgstr "Extraire de la Table"
+
+#: ../Thuban/UI/classgen.py:840
+msgid "Apply to Range"
+msgstr "Appliquer à l'intervalle"
+
+#: ../Thuban/UI/classgen.py:847
+msgid "Number of Classes:"
+msgstr "Nombre de Classes:"
+
+#: ../Thuban/UI/classgen.py:930
+msgid "Start:"
+msgstr "Début"
+
+#: ../Thuban/UI/classgen.py:961
+msgid "End:"
+msgstr "Fin:"
+
+#: ../Thuban/UI/classifier.py:164
+msgid "The Default group cannot be removed."
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:309
+#: ../Thuban/UI/classifier.py:467
+msgid "Pattern"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:306
+#: ../Thuban/UI/classifier.py:466
+msgid "Singleton"
+msgstr "Valeur unique"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Visible"
+msgstr "Visible"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Symbol"
+msgstr "Symbole"
+
+#: ../Thuban/UI/classifier.py:317 ../Thuban/UI/controls.py:33
+#: ../Thuban/UI/controls.py:177
+msgid "Value"
+msgstr "Valeur"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Label"
+msgstr "Étiquette"
+
+#: ../Thuban/UI/classifier.py:462 ../Thuban/UI/classifier.py:465
+msgid "Default"
+msgstr "Défaut"
+
+#: ../Thuban/UI/classifier.py:468
+msgid "Range"
+msgstr "Rang"
+
+#: ../Thuban/UI/classifier.py:469
+msgid "Map"
+msgstr "Carte"
+
+#: ../Thuban/UI/classifier.py:759
+msgid "Text"
+msgstr "Texte"
+
+#: ../Thuban/UI/classifier.py:760
+msgid "Integer"
+msgstr "Entier"
+
+#: ../Thuban/UI/classifier.py:761
+msgid "Decimal"
+msgstr "Décimal"
+
+#: ../Thuban/UI/classifier.py:820
+msgid "Generate Class"
+msgstr "Génerer la Classe"
+
+#: ../Thuban/UI/classifier.py:822 ../Thuban/UI/dbdialog.py:274
+msgid "Add"
+msgstr "Ajouter"
+
+#: ../Thuban/UI/classifier.py:824
+msgid "Move Up"
+msgstr "Élever"
+
+#: ../Thuban/UI/classifier.py:826
+msgid "Move Down"
+msgstr "Descendre"
+
+#: ../Thuban/UI/classifier.py:828
+msgid "Edit Symbol"
+msgstr "Éditer le Symbole"
+
+#: ../Thuban/UI/classifier.py:830 ../Thuban/UI/dbdialog.py:275
+#: ../Thuban/UI/projdialog.py:117
+msgid "Remove"
+msgstr "Éliminer"
+
+#: ../Thuban/UI/classifier.py:845
+msgid "Field: "
+msgstr "Champ: "
+
+#: ../Thuban/UI/classifier.py:1000 ../Thuban/UI/layerproperties.py:160
+msgid "Layer Properties"
+msgstr "Propriétés de la Couche"
+
+#: ../Thuban/UI/classifier.py:1167
+msgid "Select Properties"
+msgstr "Etablir les Propriétés"
+
+#: ../Thuban/UI/classifier.py:1178
+msgid "Preview:"
+msgstr "Prévisualisation"
+
+#: ../Thuban/UI/classifier.py:1195
+msgid "Change Line Color"
+msgstr "Changer la Couleur du Trait"
+
+#: ../Thuban/UI/classifier.py:1201 ../Thuban/UI/classifier.py:1216
+msgid "Transparent"
+msgstr "Transparent"
+
+#: ../Thuban/UI/classifier.py:1212
+msgid "Change Fill Color"
+msgstr "Chager la Couleur du Fond"
+
+#: ../Thuban/UI/classifier.py:1225
+msgid "Line Width: "
+msgstr "Largeur de Trait: "
+
+#: ../Thuban/UI/classifier.py:1242
+#, fuzzy
+msgid "Size: "
+msgstr "Titre: "
+
+#: ../Thuban/UI/classifier.py:1262 ../Thuban/UI/colordialog.py:52
+#: ../Thuban/UI/dbdialog.py:107 ../Thuban/UI/dbdialog.py:221
+#: ../Thuban/UI/labeldialog.py:41 ../Thuban/UI/layerproperties.py:81
+#: ../Thuban/UI/projdialog.py:205
+msgid "OK"
+msgstr "OK"
+
+#: ../Thuban/UI/classifier.py:1264 ../Thuban/UI/colordialog.py:53
+#: ../Thuban/UI/dbdialog.py:110 ../Thuban/UI/dbdialog.py:223
+#: ../Thuban/UI/labeldialog.py:42 ../Thuban/UI/projdialog.py:1033
+msgid "Cancel"
+msgstr "Annuler"
+
+#: ../Thuban/UI/colordialog.py:39
+#, fuzzy
+msgid "Select Color"
+msgstr "Sélection"
+
+#: ../Thuban/UI/controls.py:31
+msgid "Field"
+msgstr "Champ"
+
+#: ../Thuban/UI/dbdialog.py:41
+msgid "Choose layer from database"
+msgstr "Choisir une couche dans la base de données"
+
+#: ../Thuban/UI/dbdialog.py:59
+msgid "Databases"
+msgstr "Bases de Données"
+
+#: ../Thuban/UI/dbdialog.py:74
+msgid "Retrieve"
+msgstr "Retrouver"
+
+#: ../Thuban/UI/dbdialog.py:82
+msgid "Tables"
+msgstr "Tables"
+
+#: ../Thuban/UI/dbdialog.py:92
+msgid "ID Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:98
+msgid "Geometry Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:187
+msgid "Hostname:"
+msgstr "Nom de l'Hôte:"
+
+#: ../Thuban/UI/dbdialog.py:191
+msgid "Port:"
+msgstr "Port:"
+
+#: ../Thuban/UI/dbdialog.py:198
+msgid "Database Name:"
+msgstr "Base de Données:"
+
+#: ../Thuban/UI/dbdialog.py:206
+msgid "User:"
+msgstr "Utilisateur:"
+
+#: ../Thuban/UI/dbdialog.py:211
+msgid "Password:"
+msgstr "Mot de Passe:"
+
+#: ../Thuban/UI/dbdialog.py:286
+msgid "Database Management"
+msgstr "Gestion de Bases de Données"
+
+#: ../Thuban/UI/dbdialog.py:361 ../Thuban/UI/dbdialog.py:366
+msgid "Add Database"
+msgstr "Ajouter une Base de Données"
+
+#: ../Thuban/UI/dbdialog.py:367
+#, python-format
+msgid "Connection '%s' already exists"
+msgstr "La connexion '%s' existe déjà"
+
+#: ../Thuban/UI/dbdialog.py:388
+msgid "Remove Database Connection"
+msgstr "Elminer la connexion"
+
+#: ../Thuban/UI/dbdialog.py:389
+#, python-format
+msgid ""
+"The connection %s\n"
+"is still in use"
+msgstr ""
+"La connexion %s\n"
+"est toujours utilisée"
+
+#: ../Thuban/UI/dock.py:190
+msgid "Undock"
+msgstr "Déttacher"
+
+#: ../Thuban/UI/dock.py:218
+msgid "Dock"
+msgstr "Attacher"
+
+#: ../Thuban/UI/exceptiondialog.py:23 ../Thuban/UI/exceptiondialog.py:61
+msgid "Thuban: Internal Error"
+msgstr "Thuban: Errur Interne"
+
+#: ../Thuban/UI/exceptiondialog.py:43
+msgid "Proceed"
+msgstr "Continuer"
+
+#: ../Thuban/UI/exceptiondialog.py:44
+msgid "Exit Thuban now"
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:72
+msgid "Initialization not yet requested."
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:88
+msgid "Initialization successful."
+msgstr ""
+
+#: ../Thuban/UI/identifyview.py:44
+msgid "Identify Shape"
+msgstr "Identifier"
+
+#: ../Thuban/UI/identifyview.py:56
+msgid "Close Window"
+msgstr "Fermer la Fenêtre"
+
+#: ../Thuban/UI/identifyview.py:57
+msgid "Stop Identify Mode"
+msgstr "Suspendre le mode Identifier"
+
+#: ../Thuban/UI/join.py:64
+msgid "Join"
+msgstr "Joindre"
+
+#: ../Thuban/UI/join.py:71 ../Thuban/UI/join.py:72
+#, fuzzy
+msgid "Select..."
+msgstr "Sélection"
+
+#: ../Thuban/UI/join.py:100 ../Thuban/UI/join.py:108
+msgid "Table:"
+msgstr "Table: "
+
+#: ../Thuban/UI/join.py:111 ../Thuban/UI/join.py:114
+msgid "Field:"
+msgstr "Champ: "
+
+#: ../Thuban/UI/join.py:125
+msgid "Outer Join (preserves left table records)"
+msgstr "Jointure extérieure (conserve les registres à gauche)"
+
+#: ../Thuban/UI/join.py:173
+#, python-format
+msgid ""
+"Join failed:\n"
+"  %s"
+msgstr ""
+"Erreur de Jointure:\n"
+"  %s"
+
+#: ../Thuban/UI/join.py:174
+msgid "Info"
+msgstr "Information"
+
+#: ../Thuban/UI/join.py:195
+#, python-format
+msgid ""
+"The joined table has %(joined)d rows but it must have %(needed)d rows to be "
+"used with the selected layer"
+msgstr ""
+"La table à joindre possède %(joined)d lignes mais elle doit avoir %(needed)d "
+"lignes pour pouvoir être utilisée avec la couche sélectionnée"
+
+#: ../Thuban/UI/join.py:200
+msgid "Join Failed"
+msgstr "Erreur de jointure"
+
+#: ../Thuban/UI/join.py:209 ../Thuban/UI/mainwindow.py:915
+#, python-format
+msgid "Table: %s"
+msgstr "Table: %s"
+
+#: ../Thuban/UI/labeldialog.py:26
+msgid "Label Values"
+msgstr "Valeur d´étiquette"
+
+#: ../Thuban/UI/layerproperties.py:54
+msgid "Title: "
+msgstr "Titre: "
+
+#: ../Thuban/UI/layerproperties.py:65
+#, fuzzy, python-format
+msgid "Layer Type: %s"
+msgstr "Table: %s"
+
+#: ../Thuban/UI/layerproperties.py:71
+#, fuzzy
+msgid "Projection: None"
+msgstr "Projection:"
+
+#: ../Thuban/UI/layerproperties.py:73
+#, fuzzy, python-format
+msgid "Projection: %s"
+msgstr "Projection:"
+
+#: ../Thuban/UI/layerproperties.py:79 ../Thuban/UI/projdialog.py:199
+msgid "Try"
+msgstr "Essayer"
+
+#: ../Thuban/UI/layerproperties.py:80 ../Thuban/UI/projdialog.py:202
+msgid "Revert"
+msgstr "Revertir"
+
+#: ../Thuban/UI/legend.py:75
+msgid "Top Layer"
+msgstr "Couche supérieure"
+
+#: ../Thuban/UI/legend.py:79
+msgid "Raise Layer"
+msgstr "Élever la Couche"
+
+#: ../Thuban/UI/legend.py:83
+msgid "Lower Layer"
+msgstr "Abaisser la Couche"
+
+#: ../Thuban/UI/legend.py:87
+msgid "Bottom Layer"
+msgstr "Couche inférieure"
+
+#: ../Thuban/UI/legend.py:91
+msgid "Show Layer"
+msgstr "Montrer la Couche"
+
+#: ../Thuban/UI/legend.py:95
+msgid "Hide Layer"
+msgstr "Occulter la Couche"
+
+#: ../Thuban/UI/legend.py:99
+msgid "Edit Layer Properties"
+msgstr "Editer les Propriétés de la Couche"
+
+#: ../Thuban/UI/mainwindow.py:264 ../Thuban/UI/mainwindow.py:286
+#, python-format
+msgid "Unknown command %s"
+msgstr "Commande inconnue: %s"
+
+#: ../Thuban/UI/mainwindow.py:299
+#, python-format
+msgid "Unknown command ID %d"
+msgstr "ID de commande inconnue %d"
+
+#: ../Thuban/UI/mainwindow.py:338
+#, python-format
+msgid "The Dialog named %s is already open"
+msgstr "La Boîte de Dialogue %s est déjà ouverte"
+
+#: ../Thuban/UI/mainwindow.py:396
+#, python-format
+msgid "Select layer '%s' and pick a projection using Layer/Projection..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:449
+msgid "Exit"
+msgstr "Sortir"
+
+#: ../Thuban/UI/mainwindow.py:450
+msgid "The session has been modified. Do you want to save it?"
+msgstr "La session a été modifiée. Voulez-vous l'enregistrer?"
+
+#: ../Thuban/UI/mainwindow.py:465
+msgid "Open Session"
+msgstr "Ouvrir Session"
+
+#: ../Thuban/UI/mainwindow.py:487
+msgid "Save Session As"
+msgstr "Enregistrer Session Comme"
+
+#: ../Thuban/UI/mainwindow.py:561
+msgid "Select one or more data files"
+msgstr "Choisir un ou plusieurs fichiers de données"
+
+#: ../Thuban/UI/mainwindow.py:576
+msgid "Add Layer"
+msgstr "Ajouter une Couche"
+
+#: ../Thuban/UI/mainwindow.py:577 ../Thuban/UI/mainwindow.py:602
+#: ../Thuban/UI/mainwindow.py:862
+#, python-format
+msgid "Can't open the file '%s'."
+msgstr "Impossible d'ouvrir le fichier '%s'"
+
+#: ../Thuban/UI/mainwindow.py:589
+msgid "Select an image file"
+msgstr "Choisir un fichier de données image"
+
+#: ../Thuban/UI/mainwindow.py:601
+msgid "Add Image Layer"
+msgstr "Ajouter une Couche Image"
+
+#: ../Thuban/UI/mainwindow.py:629
+msgid "Add Layer from database"
+msgstr "Ajouter une Couche de la base de données"
+
+#: ../Thuban/UI/mainwindow.py:630
+#, python-format
+msgid "Can't open the database table '%s'"
+msgstr "Impossible d'ouvrir la base de données '%s'"
+
+#: ../Thuban/UI/mainwindow.py:719
+#, python-format
+msgid "Copy of `%s'"
+msgstr "Copie de `%s'"
+
+#: ../Thuban/UI/mainwindow.py:749
+#, python-format
+msgid "Layer Table: %s"
+msgstr "Table: %s"
+
+#: ../Thuban/UI/mainwindow.py:764
+#, python-format
+msgid "Map Projection: %s"
+msgstr "Projection: %s"
+
+#: ../Thuban/UI/mainwindow.py:779
+#, python-format
+msgid "Layer Projection: %s"
+msgstr "Projection de la Couche: %s"
+
+#: ../Thuban/UI/mainwindow.py:812
+msgid "Join Layer with Table"
+msgstr "Joindre Couche avec Table"
+
+#: ../Thuban/UI/mainwindow.py:834 ../Thuban/UI/mainwindow.py:1165
+msgid "Legend"
+msgstr "Légende"
+
+#: ../Thuban/UI/mainwindow.py:848 ../Thuban/UI/mainwindow.py:861
+msgid "Open Table"
+msgstr "Ouvrir Table"
+
+#: ../Thuban/UI/mainwindow.py:850
+msgid "DBF Files (*.dbf)"
+msgstr "Fichiers DBF (*.dbf)"
+
+#: ../Thuban/UI/mainwindow.py:873
+msgid "Pick the tables to close:"
+msgstr "Choisissez les tables que vous voulez fermer:"
+
+#: ../Thuban/UI/mainwindow.py:874
+msgid "Close Table"
+msgstr "Fermer Ta&ble"
+
+#: ../Thuban/UI/mainwindow.py:894
+msgid "Pick the table to show:"
+msgstr "Choisissez la table que vous voulez montrer:"
+
+#: ../Thuban/UI/mainwindow.py:895
+msgid "Show Table"
+msgstr "Montrer Table"
+
+#: ../Thuban/UI/mainwindow.py:906
+msgid "Join Tables"
+msgstr "Joindre des Tables"
+
+#: ../Thuban/UI/mainwindow.py:929
+msgid "Pick the table to rename:"
+msgstr "Choisissez la table que vous voulez renommer:"
+
+#: ../Thuban/UI/mainwindow.py:930 ../Thuban/UI/mainwindow.py:942
+msgid "Rename Table"
+msgstr "&Renommer Table"
+
+#: ../Thuban/UI/mainwindow.py:942
+#, fuzzy
+msgid "Table Title:"
+msgstr "Table: "
+
+#: ../Thuban/UI/mainwindow.py:991
+#, fuzzy
+msgid "Map Title:"
+msgstr "Titre: "
+
+#: ../Thuban/UI/mainwindow.py:991
+#, fuzzy
+msgid "Rename Map"
+msgstr "Renommer la carte"
+
+#: ../Thuban/UI/mainwindow.py:1004
+#, fuzzy
+msgid "Layer Title:"
+msgstr "Table: %s"
+
+#: ../Thuban/UI/mainwindow.py:1004
+#, fuzzy
+msgid "Rename Layer"
+msgstr "&Eliminer une Couche"
+
+#: ../Thuban/UI/mainwindow.py:1057
+#, python-format
+msgid "Thuban - %s"
+msgstr "Thuban - %s"
+
+#: ../Thuban/UI/mainwindow.py:1059
+msgid "Thuban"
+msgstr "Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1154
+msgid "&New Session"
+msgstr "&Nouvelle Session"
+
+#: ../Thuban/UI/mainwindow.py:1155
+msgid "Start a new session"
+msgstr "Établir une nouvelle Session"
+
+#: ../Thuban/UI/mainwindow.py:1156
+msgid "&Open Session..."
+msgstr "&Ouvrir Session..."
+
+#: ../Thuban/UI/mainwindow.py:1157
+msgid "Open a session file"
+msgstr "Ouvrir un fichier de session"
+
+#: ../Thuban/UI/mainwindow.py:1158
+msgid "&Save Session"
+msgstr "&Enregistrer Session"
+
+#: ../Thuban/UI/mainwindow.py:1159
+msgid "Save this session to the file it was opened from"
+msgstr ""
+"Enregistrer cette session dans le fichier depuis lequel elle a été ouverte"
+
+#: ../Thuban/UI/mainwindow.py:1160
+msgid "Save Session &As..."
+msgstr "Enregistrer Session Co&mme..."
+
+#: ../Thuban/UI/mainwindow.py:1161
+msgid "Save this session to a new file"
+msgstr "Enregistrer cette session dans un fichier nouveau"
+
+#: ../Thuban/UI/mainwindow.py:1162
+msgid "Session &Tree"
+msgstr "&Arbre de la Session"
+
+#: ../Thuban/UI/mainwindow.py:1164
+msgid "Toggle on/off the session tree analysis window"
+msgstr "Active/désactive la fenêtre d'analyse de l'arbre de session"
+
+#: ../Thuban/UI/mainwindow.py:1167
+msgid "Toggle Legend on/off"
+msgstr "Active/désactive la légende"
+
+#: ../Thuban/UI/mainwindow.py:1168
+msgid "&Database Connections..."
+msgstr "Connexions à Bases de &Données..."
+
+#: ../Thuban/UI/mainwindow.py:1171
+msgid "E&xit"
+msgstr "&Sortir"
+
+#: ../Thuban/UI/mainwindow.py:1172
+msgid "Finish working with Thuban"
+msgstr "Finit le travail avec Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1175
+msgid "&About..."
+msgstr "A &Propos..."
+
+#: ../Thuban/UI/mainwindow.py:1176
+msgid "Info about Thuban authors, version and modules"
+msgstr "Information sur les auteurs, versions et modules de Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1180 ../Thuban/UI/mainwindow.py:1228
+msgid "Pro&jection..."
+msgstr "Pro&jection..."
+
+#: ../Thuban/UI/mainwindow.py:1181
+msgid "Set or change the map projection"
+msgstr "Définit la projection de la carte"
+
+#: ../Thuban/UI/mainwindow.py:1183
+msgid "&Zoom in"
+msgstr "&Zoom+"
+
+#: ../Thuban/UI/mainwindow.py:1184
+msgid "Switch to map-mode 'zoom-in'"
+msgstr "Change le mode à 'zoom+'"
+
+#: ../Thuban/UI/mainwindow.py:1186
+msgid "Zoom &out"
+msgstr "Z&oom-"
+
+#: ../Thuban/UI/mainwindow.py:1187
+msgid "Switch to map-mode 'zoom-out'"
+msgstr "Change le mode à 'zoom-'"
+
+#: ../Thuban/UI/mainwindow.py:1189
+msgid "&Pan"
+msgstr "Dé&placement"
+
+#: ../Thuban/UI/mainwindow.py:1190
+msgid "Switch to map-mode 'pan'"
+msgstr "Change le mode à 'déplacement'"
+
+#: ../Thuban/UI/mainwindow.py:1192
+msgid "&Identify"
+msgstr "&Identifier"
+
+#: ../Thuban/UI/mainwindow.py:1194
+msgid "Switch to map-mode 'identify'"
+msgstr "Change le mode à 'identifier'"
+
+#: ../Thuban/UI/mainwindow.py:1196
+msgid "&Label"
+msgstr "&Etiquette"
+
+#: ../Thuban/UI/mainwindow.py:1197
+msgid "Add/Remove labels"
+msgstr "Ajoute/élimine des étiquettes"
+
+#: ../Thuban/UI/mainwindow.py:1199
+msgid "&Full extent"
+msgstr "E&xtension complète"
+
+#: ../Thuban/UI/mainwindow.py:1200
+msgid "Zoom to the full map extent"
+msgstr "Ajuste l'extension à la carte entière"
+
+#: ../Thuban/UI/mainwindow.py:1202
+msgid "&Full layer extent"
+msgstr "Extension de la &Couche"
+
+#: ../Thuban/UI/mainwindow.py:1203
+msgid "Zoom to the full layer extent"
+msgstr "Ajuste l'extension à celle de la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1205
+msgid "&Full selection extent"
+msgstr "Extension de la sélection"
+
+#: ../Thuban/UI/mainwindow.py:1207
+msgid "Zoom to the full selection extent"
+msgstr "Ajuste l'extension à celle de la sélection actuelle"
+
+#: ../Thuban/UI/mainwindow.py:1209
+msgid "E&xport"
+msgstr "E&xporter"
+
+#: ../Thuban/UI/mainwindow.py:1210
+msgid "Export the map to file"
+msgstr "Exporter la carte dans un fichier"
+
+#: ../Thuban/UI/mainwindow.py:1211
+msgid "Prin&t"
+msgstr "I&mprimer"
+
+#: ../Thuban/UI/mainwindow.py:1212
+msgid "Print the map"
+msgstr "Imprimer la carte"
+
+#: ../Thuban/UI/mainwindow.py:1213 ../Thuban/UI/mainwindow.py:1299
+msgid "&Rename..."
+msgstr "&Renommer..."
+
+#: ../Thuban/UI/mainwindow.py:1214
+msgid "Rename the map"
+msgstr "Renommer la carte"
+
+#: ../Thuban/UI/mainwindow.py:1215
+msgid "&Add Layer..."
+msgstr "&Ajouter une Couche..."
+
+#: ../Thuban/UI/mainwindow.py:1216
+msgid "Add a new layer to the map"
+msgstr "Ajouter une nouvelle couche à la carte actuelle"
+
+#: ../Thuban/UI/mainwindow.py:1217
+msgid "&Add Image Layer..."
+msgstr "Ajouter une Couche I&mage..."
+
+#: ../Thuban/UI/mainwindow.py:1218
+msgid "Add a new image layer to the map"
+msgstr "Ajouter une nouvelle couche image à la carte actuelle"
+
+#: ../Thuban/UI/mainwindow.py:1220
+msgid "Add &Database Layer..."
+msgstr "Ajouter une Couche depuis une Base de &Données..."
+
+#: ../Thuban/UI/mainwindow.py:1221
+msgid "Add a new database layer to active map"
+msgstr ""
+"Ajouter une nouvelle couche à la carte actuelle depuis une base de données"
+
+#: ../Thuban/UI/mainwindow.py:1223
+msgid "&Remove Layer"
+msgstr "&Eliminer une Couche"
+
+#: ../Thuban/UI/mainwindow.py:1224
+msgid "Remove selected layer"
+msgstr "Éliminer la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1230
+msgid "Specify projection for selected layer"
+msgstr "Spécifier la projection de la couche selectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1231
+msgid "&Duplicate"
+msgstr "&Dupliquer"
+
+#: ../Thuban/UI/mainwindow.py:1232
+msgid "Duplicate selected layer"
+msgstr "Dupliquer la couche selectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1234
+msgid "Re&name ..."
+msgstr "&Renommer..."
+
+#: ../Thuban/UI/mainwindow.py:1235
+msgid "Rename selected layer"
+msgstr "Change le nom de la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1237
+msgid "&Raise"
+msgstr "Ele&ver"
+
+#: ../Thuban/UI/mainwindow.py:1238
+msgid "Raise selected layer"
+msgstr "Élève de niveau la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1240
+msgid "&Lower"
+msgstr "&Abaisser"
+
+#: ../Thuban/UI/mainwindow.py:1241
+msgid "Lower selected layer"
+msgstr "Abaisser le niveau de la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1243
+msgid "&Show"
+msgstr "&Montrer"
+
+#: ../Thuban/UI/mainwindow.py:1244
+msgid "Make selected layer visible"
+msgstr "Rend visible la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1246
+msgid "&Hide"
+msgstr "&Occulter"
+
+#: ../Thuban/UI/mainwindow.py:1247
+msgid "Make selected layer unvisible"
+msgstr "Rend invisible la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1249
+msgid "Show Ta&ble"
+msgstr "Montrer Ta&ble"
+
+#: ../Thuban/UI/mainwindow.py:1250
+msgid "Show the selected layer's table"
+msgstr "Affiche la table de la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1252
+msgid "&Properties..."
+msgstr "&Propriétés..."
+
+#: ../Thuban/UI/mainwindow.py:1254
+msgid "Edit the properties of the selected layer"
+msgstr "Change les propriétés de la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1255
+msgid "&Join Table..."
+msgstr "&Joindre Table..."
+
+#: ../Thuban/UI/mainwindow.py:1257
+msgid "Join and attach a table to the selected layer"
+msgstr "Joint et rajoute una table à la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1260
+msgid "&Top"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1261
+#, fuzzy
+msgid "Put selected layer to the top"
+msgstr "Dupliquer la couche selectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1263
+#, fuzzy
+msgid "&Bottom"
+msgstr "Couche inférieure"
+
+#: ../Thuban/UI/mainwindow.py:1264
+#, fuzzy
+msgid "Put selected layer to the bottom"
+msgstr "Dupliquer la couche selectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1266
+#, fuzzy
+msgid "&Visible"
+msgstr "Visible"
+
+#: ../Thuban/UI/mainwindow.py:1268
+#, fuzzy
+msgid "Toggle visibility of selected layer"
+msgstr "Élève de niveau la couche sélectionnée"
+
+#: ../Thuban/UI/mainwindow.py:1285
+msgid "&Unjoin Table..."
+msgstr "Déjoi&ndre Table..."
+
+#: ../Thuban/UI/mainwindow.py:1287
+msgid "Undo the last join operation"
+msgstr "Défait la dernière jointure"
+
+#: ../Thuban/UI/mainwindow.py:1294
+msgid "&Open..."
+msgstr "&Ouvrir..."
+
+#: ../Thuban/UI/mainwindow.py:1295
+msgid "Open a DBF-table from a file"
+msgstr "Ouvre une table depuis un fichier DBF"
+
+#: ../Thuban/UI/mainwindow.py:1296
+msgid "&Close..."
+msgstr "&Fermer..."
+
+#: ../Thuban/UI/mainwindow.py:1298
+msgid "Close one or more tables from a list"
+msgstr "Ferme une ou plusieurs tables dans une liste"
+
+#: ../Thuban/UI/mainwindow.py:1301
+msgid "Rename one or more tables"
+msgstr "Change le nom d'une ou plusieurs tables"
+
+#: ../Thuban/UI/mainwindow.py:1302
+msgid "&Show..."
+msgstr "&Montrer..."
+
+#: ../Thuban/UI/mainwindow.py:1304
+msgid "Show one or more tables in a dialog"
+msgstr "Montre le contenu d'une ou plusieurs tables"
+
+#: ../Thuban/UI/mainwindow.py:1305
+msgid "&Join..."
+msgstr "&Joindre..."
+
+#: ../Thuban/UI/mainwindow.py:1307
+msgid "Join two tables creating a new one"
+msgstr "Définit la jointure de deux tables dans une nouvelle table"
+
+#: ../Thuban/UI/mainwindow.py:1331
+msgid "&File"
+msgstr "&Fichier"
+
+#: ../Thuban/UI/mainwindow.py:1337
+msgid "&Map"
+msgstr "&Carte"
+
+#: ../Thuban/UI/mainwindow.py:1338
+msgid "&Layer"
+msgstr "Couc&he"
+
+#: ../Thuban/UI/mainwindow.py:1352
+msgid "&Table"
+msgstr "&Table"
+
+#: ../Thuban/UI/mainwindow.py:1358
+msgid "&Help"
+msgstr "&Aide"
+
+#: ../Thuban/UI/menu.py:90
+#, python-format
+msgid "Submenu %s doesn't exist"
+msgstr "Le sous-menu %s n'existe pas"
+
+#: ../Thuban/UI/projdialog.py:62 ../Thuban/UI/projdialog.py:776
+msgid "Transverse Mercator"
+msgstr "Marcator Transverse"
+
+#: ../Thuban/UI/projdialog.py:63 ../Thuban/UI/projdialog.py:842
+msgid "Universal Transverse Mercator"
+msgstr "Mercator Transverse Universelle (UTM)"
+
+#: ../Thuban/UI/projdialog.py:64 ../Thuban/UI/projdialog.py:918
+msgid "Lambert Conic Conformal"
+msgstr "Lambert Conique Conforme"
+
+#: ../Thuban/UI/projdialog.py:65 ../Thuban/UI/projdialog.py:66
+#: ../Thuban/UI/projdialog.py:968
+msgid "Geographic"
+msgstr "Géographique"
+
+#: ../Thuban/UI/projdialog.py:110
+msgid "Import..."
+msgstr "Importer..."
+
+#: ../Thuban/UI/projdialog.py:113
+msgid "Export..."
+msgstr "Exporter..."
+
+#: ../Thuban/UI/projdialog.py:122
+msgid "Show EPSG:"
+msgstr "Montrer EPSG:"
+
+#: ../Thuban/UI/projdialog.py:124
+msgid "Normal"
+msgstr "Normal"
+
+#: ../Thuban/UI/projdialog.py:127
+msgid "Deprecated"
+msgstr "Déconseillé"
+
+#: ../Thuban/UI/projdialog.py:138
+msgid "Edit"
+msgstr "Édition"
+
+#: ../Thuban/UI/projdialog.py:148
+msgid "Name:"
+msgstr "Nom:"
+
+#: ../Thuban/UI/projdialog.py:156
+msgid "Projection:"
+msgstr "Projection:"
+
+#: ../Thuban/UI/projdialog.py:167 ../Thuban/UI/projdialog.py:648
+msgid "<Unknown>"
+msgstr "<Inconnu>"
+
+#: ../Thuban/UI/projdialog.py:183
+msgid "New"
+msgstr "Nouvelle"
+
+#: ../Thuban/UI/projdialog.py:186
+msgid "Add to List"
+msgstr "Ajouter à la liste"
+
+#: ../Thuban/UI/projdialog.py:190
+msgid "Update"
+msgstr "Actualiser"
+
+#: ../Thuban/UI/projdialog.py:295
+#, python-format
+msgid ""
+"Warnings when reading \"%s\":\n"
+"\n"
+"%s"
+msgstr ""
+"Messages d'alerte en lisant \"%s\":\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/projdialog.py:306
+msgid "Import"
+msgstr "Importer"
+
+#: ../Thuban/UI/projdialog.py:319 ../Thuban/UI/projdialog.py:617
+msgid "Warnings"
+msgstr "Alertes"
+
+#: ../Thuban/UI/projdialog.py:337 ../Thuban/UI/tableview.py:386
+msgid "Export"
+msgstr "Exporter"
+
+#: ../Thuban/UI/projdialog.py:389
+msgid "The following error occured:\n"
+msgstr "L'erreur suivante s'est produite:\n"
+
+#: ../Thuban/UI/projdialog.py:391
+msgid "Error"
+msgstr "Erreur"
+
+#: ../Thuban/UI/projdialog.py:460
+msgid "No Projections selected"
+msgstr "Projections non spécifiées"
+
+#: ../Thuban/UI/projdialog.py:470
+#, python-format
+msgid "Source of Projection: %s"
+msgstr "Source de la Projection: %s"
+
+#: ../Thuban/UI/projdialog.py:502
+msgid "Multiple Projections selected"
+msgstr "Plusieurs projections spécifiées"
+
+#: ../Thuban/UI/projdialog.py:649
+msgid "Airy"
+msgstr "Airy"
+
+#: ../Thuban/UI/projdialog.py:650
+msgid "Bessel 1841"
+msgstr "Bessel 1841"
+
+#: ../Thuban/UI/projdialog.py:651
+msgid "Clarke 1866"
+msgstr "Clarke 1866"
+
+#: ../Thuban/UI/projdialog.py:652
+msgid "Clarke 1880"
+msgstr "Clarke 1880"
+
+#: ../Thuban/UI/projdialog.py:653
+msgid "GRS 1980 (IUGG, 1980)"
+msgstr "GRS 1980 (IUGG, 1980)"
+
+#: ../Thuban/UI/projdialog.py:654
+msgid "International 1909 (Hayford)"
+msgstr "International 1909 (Hayford)"
+
+#: ../Thuban/UI/projdialog.py:655
+msgid "WGS 84"
+msgstr "WGS 84"
+
+#: ../Thuban/UI/projdialog.py:667
+msgid "Ellipsoid:"
+msgstr "Ellipsoïde:"
+
+#: ../Thuban/UI/projdialog.py:716
+msgid ""
+"Thuban does not know the parameters\n"
+"for the current projection and cannot\n"
+"display a configuration panel.\n"
+"\n"
+"The unidentified set of parameters is:\n"
+"\n"
+msgstr ""
+"Thuban ne connait pas les paramètres de la \n"
+"projection actuelle et ne peut pas montrer \n"
+"un panneau de configuration.\n"
+"\n"
+"L'ensemble de paramètres inconnu est:\n"
+"\n"
+
+#: ../Thuban/UI/projdialog.py:762
+msgid "Latitude:"
+msgstr "Latitude:"
+
+#: ../Thuban/UI/projdialog.py:764
+msgid "Longitude:"
+msgstr "Longitude:"
+
+#: ../Thuban/UI/projdialog.py:766 ../Thuban/UI/projdialog.py:910
+msgid "False Easting:"
+msgstr "Faux Est:"
+
+#: ../Thuban/UI/projdialog.py:768 ../Thuban/UI/projdialog.py:912
+msgid "False Northing:"
+msgstr "Faux Nord:"
+
+#: ../Thuban/UI/projdialog.py:770
+msgid "Scale Factor:"
+msgstr "Facteur d'Echelle"
+
+#: ../Thuban/UI/projdialog.py:821
+msgid "Propose"
+msgstr "Proposer"
+
+#: ../Thuban/UI/projdialog.py:823
+msgid "Southern Hemisphere"
+msgstr "Hémisphère Sud"
+
+#: ../Thuban/UI/projdialog.py:833
+msgid "Zone:"
+msgstr "Zone:"
+
+#: ../Thuban/UI/projdialog.py:870
+msgid "Can not propose: No bounding box found."
+msgstr "Impossible de proposer: pas de boîte enveloppante"
+
+#: ../Thuban/UI/projdialog.py:871 ../Thuban/UI/projdialog.py:1008
+msgid "Projection: Propose UTM Zone"
+msgstr "Projection: Proposer Zone UTM"
+
+#: ../Thuban/UI/projdialog.py:901
+msgid "Latitude of first standard parallel:"
+msgstr "Latitude du premier parallèle standard"
+
+#: ../Thuban/UI/projdialog.py:904
+msgid "Latitude of second standard parallel:"
+msgstr "Latitude du deuxième parallèle standard"
+
+#: ../Thuban/UI/projdialog.py:906
+msgid "Central Meridian:"
+msgstr "Méridien Central:"
+
+#: ../Thuban/UI/projdialog.py:908
+msgid "Latitude of origin:"
+msgstr "Latitude de l'origine:"
+
+#: ../Thuban/UI/projdialog.py:958
+msgid "Degrees"
+msgstr "Degrés"
+
+#: ../Thuban/UI/projdialog.py:959
+msgid "Radians"
+msgstr "Radians"
+
+#: ../Thuban/UI/projdialog.py:992
+msgid "Source Data is in: "
+msgstr "Les données d'origine sont en: "
+
+#: ../Thuban/UI/projdialog.py:1021
+msgid "The current map extent center lies in UTM Zone"
+msgstr "Le centre de l'extension actuelle de la carte appartien à la Zone UTM"
+
+#: ../Thuban/UI/projdialog.py:1031
+msgid "Take"
+msgstr "Choisir"
+
+#: ../Thuban/UI/projlist.py:51
+msgid "Available Projections"
+msgstr "Projections Disponibles"
+
+#: ../Thuban/UI/projlist.py:112
+msgid "<None>"
+msgstr "<Néant>"
+
+#: ../Thuban/UI/projlist.py:117
+#, python-format
+msgid "%s (current)"
+msgstr "%s (actuelle)"
+
+#: ../Thuban/UI/rasterlayerproperties.py:41
+msgid "GDAL image information unavailable. See About box for details."
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:49
+#, fuzzy
+msgid "Extent (lat-lon): None"
+msgstr "Extension (lat-lon):"
+
+#: ../Thuban/UI/rasterlayerproperties.py:56
+#, fuzzy
+msgid "Image Properties"
+msgstr "Propriétés de la Couche"
+
+#: ../Thuban/UI/rasterlayerproperties.py:61
+#, python-format
+msgid "Source: %s"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:71
+#, fuzzy, python-format
+msgid "Driver: %s"
+msgstr "Champ: %s"
+
+#: ../Thuban/UI/rasterlayerproperties.py:74
+#, python-format
+msgid "Size: %ix%i"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:77
+#, fuzzy, python-format
+msgid "Number of Bands: %i"
+msgstr "Nombre de Classes:"
+
+#: ../Thuban/UI/rasterlayerproperties.py:93
+msgid "Mask Type"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:99
+msgid "Opacity:"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:381
+msgid "Replace Selection"
+msgstr "Remplacer la Sélection"
+
+#: ../Thuban/UI/tableview.py:382
+msgid "Refine Selection"
+msgstr "Raffiner la Sélection"
+
+#: ../Thuban/UI/tableview.py:383
+msgid "Add to Selection"
+msgstr "Ajouter à la Sélection"
+
+#: ../Thuban/UI/tableview.py:385
+msgid "Query"
+msgstr "Chercher"
+
+#: ../Thuban/UI/tableview.py:387
+msgid "Export Selection"
+msgstr "Exporter la Sélection"
+
+#: ../Thuban/UI/tableview.py:413
+msgid "Selection"
+msgstr "Sélection"
+
+#: ../Thuban/UI/tableview.py:455
+#, python-format
+msgid "%i rows (%i selected), %i columns"
+msgstr "%i lignes (%i selectionnées), %i colonnes"
+
+#: ../Thuban/UI/tableview.py:535
+msgid "Export Table To"
+msgstr "Exporter Table Sous"
+
+#: ../Thuban/UI/tableview.py:536
+msgid "DBF Files (*.dbf)|*.dbf|"
+msgstr "Fichiers DBF (*.dbf)|*.dbf|"
+
+#: ../Thuban/UI/tableview.py:537
+msgid "CSV Files (*.csv)|*.csv|"
+msgstr "Fichiers CSV (*.csv)|*.csv|"
+
+#: ../Thuban/UI/tableview.py:538
+msgid "All Files (*.*)|*.*"
+msgstr "Tous (*.*)|*.*"
+
+#: ../Thuban/UI/tree.py:226
+msgid "Session"
+msgstr "Session"
+
+#: ../Thuban/UI/view.py:285
+msgid "Export Map"
+msgstr "Exporter la carte"
+
+#~ msgid "Type: %s"
+#~ msgstr "Type: %s"
+
+#~ msgid "Projection: UTM Parameters"
+#~ msgstr "Projection: Paramètres UTM"
+
+#~ msgid "UTM Zone"
+#~ msgstr "Zone UTM"
+
+#~ msgid "Ellipsoid"
+#~ msgstr "Ellipsoïde"

Added: packages/thuban/branches/upstream/current/po/hu.po
===================================================================
--- packages/thuban/branches/upstream/current/po/hu.po	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/po/hu.po	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1830 @@
+# Hungarian Translation for Thuban.
+# Copyright (C) 2004 Norbert Solymosi
+# This file is distributed under the same license as the Thuban package.
+# Norbert Solymosi <Solymosi.Norbert at aotk.szie.hu>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Thuban 1.0.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-03-13 20:15+0000\n"
+"PO-Revision-Date: 2004-11-09 11:31+0100\n"
+"Last-Translator: Solymosi Norbert <Solymosi.Norbert at aotk.szie.hu>\n"
+"Language-Team: hungarian <Solymosi.Norbert at aotk.szie.hu>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../Thuban/version.py:189
+#, python-format
+msgid "%s %s < %s"
+msgstr "%s %s < %s"
+
+#: ../Thuban/version.py:195
+#, python-format
+msgid "Thuban was compiled with wx %(wxproj-wx)s but wxPython is %(wxPython)s"
+msgstr ""
+"Thuban fordításához wx %(wxproj-wx)s használtak, míg a wxPython %(wxPython)s"
+
+#: ../Thuban/Lib/connector.py:65
+#, python-format
+msgid "no receivers for channel %s of %s"
+msgstr "nincsenek vevõk a csatornához %s of %s"
+
+#: ../Thuban/Lib/connector.py:70
+#, python-format
+msgid "receiver %s%s is not connected to channel %s of %s"
+msgstr "a vevõ %s%s nem kapcsolódott a csatornájához %s ennek %s"
+
+#: ../Thuban/Lib/connector.py:94
+#, python-format
+msgid "Warning: %s.%s: %s%s\n"
+msgstr "Figyelmeztetés: %s.%s: %s%s\n"
+
+#: ../Thuban/Lib/connector.py:118
+#, python-format
+msgid "\tmethod %s of %s"
+msgstr "\teljárás %s ehhez %s"
+
+#: ../Thuban/Lib/fileutil.py:87 ../Thuban/Lib/fileutil.py:141
+msgid "first argument must be an absolute filename"
+msgstr "az elsõ résznek teljes fájlnének kell lennie"
+
+#: ../Thuban/Lib/fileutil.py:138
+msgid "Both parameters must have a drive letter"
+msgstr "Mindkét paraméternek egy meghajtó betût kell tartalmaznia???"
+
+#: ../Thuban/Lib/fileutil.py:198
+msgid "No implementation of get_application_dir available for platform"
+msgstr "A platformra nem elérhetõ a get_application_dir"
+
+#: ../Thuban/Lib/fileutil.py:208
+msgid "No implementation of relative_filename available for platform"
+msgstr "A platformra nem elérhetõ a relative_filename"
+
+#: ../Thuban/Model/classgen.py:338
+msgid "invalid index"
+msgstr "érvénytelen index"
+
+#: ../Thuban/Model/classification.py:309 ../Thuban/UI/classifier.py:758
+msgid "None"
+msgstr "Nincs"
+
+#: ../Thuban/Model/classification.py:325
+msgid "Line Color"
+msgstr "Vonalszín"
+
+#: ../Thuban/Model/classification.py:327
+#, python-format
+msgid "Line Width: %s"
+msgstr "Vonalszélesség: %s"
+
+#: ../Thuban/Model/classification.py:333
+#, fuzzy, python-format
+msgid "Size: %s"
+msgstr "Méret:"
+
+#: ../Thuban/Model/classification.py:336
+msgid "Fill"
+msgstr "Kitölt"
+
+#: ../Thuban/Model/classification.py:342 ../Thuban/UI/classifier.py:841
+msgid "Classification"
+msgstr "Osztályozás"
+
+#: ../Thuban/Model/classification.py:436
+msgid "lineWidth < 1"
+msgstr "vonalvastagság < 1"
+
+#: ../Thuban/Model/classification.py:451
+msgid "size < 1"
+msgstr "méret < 1"
+
+#: ../Thuban/Model/classification.py:656 ../Thuban/UI/classifier.py:528
+msgid "DEFAULT"
+msgstr "ALAPÉRTELMEZETT"
+
+#: ../Thuban/Model/data.py:316
+msgid "Table not compatible with shapestore."
+msgstr "A tábla nem kompatibilis a shapesztorral."
+
+#: ../Thuban/Model/extension.py:90
+#, python-format
+msgid "Extension: %s"
+msgstr "Kiterjesztés: %s"
+
+#: ../Thuban/Model/label.py:91
+#, fuzzy, python-format
+msgid "Number of labels: %d"
+msgstr "Osztályok száma:"
+
+#: ../Thuban/Model/label.py:92
+#, fuzzy, python-format
+msgid "Label Layer: %s"
+msgstr "Tábla: %s"
+
+#: ../Thuban/Model/layer.py:298 ../Thuban/Model/layer.py:566
+#: ../Thuban/Model/session.py:432
+#, python-format
+msgid "Filename: %s"
+msgstr "Fájlnév: %s"
+
+#: ../Thuban/Model/layer.py:301 ../Thuban/Model/layer.py:569
+msgid "Shown"
+msgstr "Megjelenített"
+
+#: ../Thuban/Model/layer.py:303 ../Thuban/Model/layer.py:571
+msgid "Hidden"
+msgstr "Rejtett"
+
+#: ../Thuban/Model/layer.py:304
+#, python-format
+msgid "Shapes: %d"
+msgstr "Alakzat: %d"
+
+#: ../Thuban/Model/layer.py:308 ../Thuban/Model/layer.py:575
+#: ../Thuban/Model/map.py:287 ../Thuban/UI/rasterlayerproperties.py:51
+#, python-format
+msgid "Extent (lat-lon): (%g, %g, %g, %g)"
+msgstr "Kiterjedés (szélesség-hosszúság): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/layer.py:310 ../Thuban/Model/layer.py:577
+msgid "Extent (lat-lon):"
+msgstr "Kiterjedés (szélesség-hosszúság): "
+
+#: ../Thuban/Model/layer.py:311
+#, python-format
+msgid "Shapetype: %s"
+msgstr "Alakzat-típus: %s"
+
+#: ../Thuban/Model/layer.py:314 ../Thuban/Model/layer.py:580
+#: ../Thuban/Model/map.py:292
+msgid "Projection"
+msgstr "Vetület"
+
+#: ../Thuban/Model/layer.py:319 ../Thuban/Model/layer.py:583
+#, python-format
+msgid "Layer '%s'"
+msgstr "Réteg '%s'"
+
+#: ../Thuban/Model/load.py:78
+#, python-format
+msgid "Invalid hexadecimal color specification %s"
+msgstr "Hibás hexadecimális színmeghatározás: '%s'."
+
+#: ../Thuban/Model/load.py:81
+#, python-format
+msgid "Invalid color specification %s"
+msgstr "Hibás színmeghatározás: '%s'."
+
+#: ../Thuban/Model/load.py:544
+msgid "xml field type differs from database!"
+msgstr "xml mezõ típusa különbözik az adatbázistól!"
+
+#: ../Thuban/Model/load.py:609
+msgid "Classification range is not a number!"
+msgstr "Az osztályozási tartomány nem szám!"
+
+#: ../Thuban/Model/map.py:53
+msgid "Labels"
+msgstr "Címkék"
+
+#: ../Thuban/Model/map.py:290
+#, python-format
+msgid "Extent (projected): (%g, %g, %g, %g)"
+msgstr "Kiterjedés (vetületi): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/map.py:301
+#, python-format
+msgid "Map: %s"
+msgstr "Térkép: %s"
+
+#: ../Thuban/Model/proj.py:84 ../Thuban/Model/resource.py:179
+msgid "Unknown"
+msgstr "Ismeretlen"
+
+#: ../Thuban/Model/resource.py:46
+#, python-format
+msgid ""
+"No GDAL support because module '%s' cannot be imported. Python exception: '%"
+"s'"
+msgstr ""
+"Nincs GDAL támogatás, mert a '%s' modult nem lehet betölteni. Python "
+"kivétel: '%s'"
+
+#: ../Thuban/Model/resource.py:135 ../Thuban/Model/resource.py:155
+#, python-format
+msgid "Could not read \"%s\": %s"
+msgstr "Olvashatalan \"%s\": %s"
+
+#: ../Thuban/Model/resource.py:187
+#, python-format
+msgid "Error in projection \"%s\": %s"
+msgstr "Hiba a vetületben \"%s\": %s"
+
+#: ../Thuban/Model/save.py:352
+msgid "Unsupported group type in classification"
+msgstr "Osztályozásban nem támogatott csoport típus"
+
+#: ../Thuban/Model/session.py:430
+msgid "Filename:"
+msgstr "Fájlnév:"
+
+#: ../Thuban/Model/session.py:435
+msgid "Modified"
+msgstr "Módosítva"
+
+#: ../Thuban/Model/session.py:437
+msgid "Unmodified"
+msgstr "Változatlan"
+
+#: ../Thuban/Model/session.py:442
+#, python-format
+msgid "Session: %s"
+msgstr "Munkafolyamat: %s"
+
+#: ../Thuban/Model/session.py:448
+msgid "unnamed session"
+msgstr "elnevezendõ munkafolyamat"
+
+#: ../Thuban/Model/session.py:450
+msgid "unnamed map"
+msgstr "elnevezendõ térkép"
+
+#: ../Thuban/UI/about.py:28
+msgid "About Thuban"
+msgstr "Thuban névjegye"
+
+#: ../Thuban/UI/about.py:47
+msgid "French"
+msgstr "Francia"
+
+#: ../Thuban/UI/about.py:48
+msgid "German"
+msgstr "Német"
+
+#: ../Thuban/UI/about.py:50
+msgid "Hungarian"
+msgstr ""
+
+#: ../Thuban/UI/about.py:51
+msgid "Italian"
+msgstr "Olasz"
+
+#: ../Thuban/UI/about.py:52
+msgid "Portuguese (Brazilian)"
+msgstr "Portugál (Brazil)"
+
+#: ../Thuban/UI/about.py:53
+msgid "Russian"
+msgstr "Orosz"
+
+#: ../Thuban/UI/about.py:54
+msgid "Spanish"
+msgstr "Spanyol"
+
+#: ../Thuban/UI/about.py:63 ../Thuban/UI/about.py:65 ../Thuban/UI/about.py:67
+msgid "- not available"
+msgstr "- nem elérhetõ"
+
+#: ../Thuban/UI/about.py:72
+msgid "Currently using:\n"
+msgstr "Jelenleg használt:\n"
+
+#: ../Thuban/UI/about.py:78
+#, python-format
+msgid "\tInternal encoding: %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:84
+msgid "Compiled for:\n"
+msgstr "A fordításhoz alapul szolgált:\n"
+
+#: ../Thuban/UI/about.py:90
+msgid "Extensions:\n"
+msgstr "Kiterjesztések:\n"
+
+#: ../Thuban/UI/about.py:95 ../Thuban/UI/about.py:144
+msgid "\tNone registered.\n"
+msgstr "\tNincs regisztrálva.\n"
+
+#: ../Thuban/UI/about.py:98
+msgid "Maintainers:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:103
+msgid "Lead Developer:\n"
+msgstr "Vezetõ fejlesztõ:\n"
+
+#: ../Thuban/UI/about.py:106
+msgid "Developers:\n"
+msgstr "Fejlesztõk:\n"
+
+#: ../Thuban/UI/about.py:111
+msgid "Translators:\n"
+msgstr "Fordítók:\n"
+
+#: ../Thuban/UI/about.py:116
+msgid "Other Contributors:\n"
+msgstr "Egyéb közremûködõk:\n"
+
+#: ../Thuban/UI/about.py:122
+msgid ""
+"Questions and comments can be sent to the following addresses:\n"
+"\tGeneral list (public):\n"
+"\t\t<thuban-list at intevation.de>\n"
+"\tDevelopers list (public):\n"
+"\t\t<thuban-devel at intevation.de>\n"
+"\tThuban team at Intevation:\n"
+"\t\t<thuban at intevation.de>\n"
+msgstr ""
+"A felmerülõ kérdéseket és észrevételeket a következõ címre várjuk:\n"
+"\tÁltalános lista (nyilvános):\n"
+"\t\t<thuban-list at intevation.de>\n"
+"\tFejlesztõ lista (nyilvános):\n"
+"\t\t<thuban-devel at intevation.de>\n"
+"\tIntevation Thuban csoportja:\n"
+"\t\t<thuban at intevation.de>\n"
+
+#: ../Thuban/UI/about.py:130
+msgid ""
+"Details on the registered extensions:\n"
+"\n"
+msgstr ""
+"A regisztrált kiterjesztések részletei:\n"
+"\n"
+
+#: ../Thuban/UI/about.py:135
+#, python-format
+msgid "Copyright %s\n"
+msgstr "Copyright: %s\n"
+
+#: ../Thuban/UI/about.py:136
+msgid "Authors:\n"
+msgstr "Szerzõk:\n"
+
+#: ../Thuban/UI/about.py:149
+msgid ""
+"Thuban is a program for exploring geographic data.\n"
+"\n"
+msgstr ""
+"A Thuban földrajzi adatok elemzését szolgáló szoftver.\n"
+"\n"
+
+#: ../Thuban/UI/about.py:151
+msgid "Thuban is licensed under the GNU GPL"
+msgstr "A Thuban-ra a GNU GPL liszensz feltételei vonatkoznak"
+
+#: ../Thuban/UI/about.py:160 ../Thuban/UI/classgen.py:91
+#: ../Thuban/UI/dbdialog.py:276 ../Thuban/UI/dock.py:371
+#: ../Thuban/UI/join.py:66 ../Thuban/UI/layerproperties.py:82
+#: ../Thuban/UI/projdialog.py:209 ../Thuban/UI/tableview.py:388
+msgid "Close"
+msgstr "Bezár"
+
+#: ../Thuban/UI/altpathdialog.py:24
+#, fuzzy, python-format
+msgid "Select an alternative data file for %s"
+msgstr "Válasszon ki egy vagy több adatfájlt"
+
+#: ../Thuban/UI/altpathdialog.py:31 ../Thuban/UI/mainwindow.py:563
+msgid "Shapefiles (*.shp)"
+msgstr "Shape-fájlok (*.shp)"
+
+#: ../Thuban/UI/altpathdialog.py:32 ../Thuban/UI/mainwindow.py:564
+#: ../Thuban/UI/mainwindow.py:852
+msgid "All Files (*.*)"
+msgstr "Minden fájlt (*.*)"
+
+#: ../Thuban/UI/altpathdialog.py:47
+#, python-format
+msgid ""
+"Found the following as an alternative for %s.\n"
+"%s\n"
+"\n"
+" Please confirm with Yes or select alternative with No."
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:49
+msgid "Alternative Path"
+msgstr ""
+
+#: ../Thuban/UI/application.py:110 ../Thuban/UI/application.py:122
+msgid "Cannot import the thubanstart module\n"
+msgstr "A thubanstart modul nem beolvasható\n"
+
+#: ../Thuban/UI/application.py:115
+msgid "No thubanstart module available\n"
+msgstr "Nincs elérhetõ thubanstart modul\n"
+
+#: ../Thuban/UI/application.py:126
+msgid "No ~/.thuban directory\n"
+msgstr "Nincs ~/.thuban könyvtár\n"
+
+#: ../Thuban/UI/application.py:166
+msgid ""
+"This is the wxPython-based Graphical User Interface for exploring geographic "
+"data"
+msgstr ""
+"Ez  a wxPython alapú grafikus felhasználói felület a földrajzi adatok "
+"elemzéséhez"
+
+#: ../Thuban/UI/application.py:254
+msgid ""
+"The current session contains Image layers,\n"
+"but the GDAL library is not available to draw them."
+msgstr ""
+"A jelenlegi munkafolyamat tartalmaz kép-réteget,\n"
+"de GDAL könyvtár nem elérhetõ a megjelenítéséhez."
+
+#: ../Thuban/UI/application.py:259
+msgid "Library not available"
+msgstr "A könyvtár nem létezik."
+
+#: ../Thuban/UI/application.py:268 ../Thuban/UI/mainwindow.py:476
+msgid "DB Connection Parameters"
+msgstr "Adatbázis-kapcsolati paraméterek"
+
+#: ../Thuban/UI/application.py:364
+#, python-format
+msgid ""
+"An unhandled exception occurred:\n"
+"%s\n"
+"(please report to http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+msgstr ""
+"Nem kezelt kivétel jelentkezett:\n"
+"%s\n"
+"(légyszi küldjed ide: http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/classgen.py:43
+msgid "Uniform Distribution"
+msgstr "Egyenletes eloszlás"
+
+#: ../Thuban/UI/classgen.py:44
+msgid "Unique Values"
+msgstr "Egyedi értékek"
+
+#: ../Thuban/UI/classgen.py:45
+msgid "Quantiles from Table"
+msgstr "Kvantilisek a táblázatból"
+
+#: ../Thuban/UI/classgen.py:47
+msgid "Custom Ramp"
+msgstr "Egyéni küszöb"
+
+#: ../Thuban/UI/classgen.py:48
+msgid "Grey Ramp"
+msgstr "Szürke küszöb"
+
+#: ../Thuban/UI/classgen.py:49
+msgid "Red Ramp"
+msgstr "Vörös küszöb"
+
+#: ../Thuban/UI/classgen.py:50
+msgid "Green Ramp"
+msgstr "Zöld küszöb"
+
+#: ../Thuban/UI/classgen.py:51
+msgid "Blue Ramp"
+msgstr "Kék küszöb"
+
+#: ../Thuban/UI/classgen.py:52
+msgid "Green-to-Red Ramp"
+msgstr "Zöld-Vörös küszöb"
+
+#: ../Thuban/UI/classgen.py:53
+msgid "Hot-to-Cold Ramp"
+msgstr "Forró-Hideg küszöb"
+
+#: ../Thuban/UI/classgen.py:69
+msgid "Generate Classification"
+msgstr "Osztályozás generálása"
+
+#: ../Thuban/UI/classgen.py:90
+msgid "Generate"
+msgstr "Létrehozás"
+
+#: ../Thuban/UI/classgen.py:119
+#, python-format
+msgid "Field: %s"
+msgstr "Mezõ: %s"
+
+#: ../Thuban/UI/classgen.py:123 ../Thuban/UI/classifier.py:976
+#, python-format
+msgid "Data Type: %s"
+msgstr "Adattípus: %s"
+
+#: ../Thuban/UI/classgen.py:127
+msgid "Generate:"
+msgstr "Generálás:"
+
+#: ../Thuban/UI/classgen.py:137
+msgid "Color Scheme:"
+msgstr "Színséma:"
+
+#: ../Thuban/UI/classgen.py:161
+msgid "Fix Border Color"
+msgstr "Határszín rögzítése"
+
+#: ../Thuban/UI/classgen.py:168 ../Thuban/UI/classgen.py:936
+#: ../Thuban/UI/classgen.py:967
+msgid "Change"
+msgstr "Módosít"
+
+#: ../Thuban/UI/classgen.py:274
+msgid ""
+"Based on the data from the table and the input\n"
+"values, the exact quantiles could not be generated.\n"
+"\n"
+"Accept a close estimate?"
+msgstr ""
+"Az egzakt kvantilisek nem generálhatók a\n"
+"táblázatból származó és beolvasott adatokra alapozva.\n"
+"\n"
+"Elfogadsz egy jó közelítést?"
+
+#: ../Thuban/UI/classgen.py:277
+msgid "Problem with Quantiles"
+msgstr "Probléma a kvantilisekkel"
+
+#: ../Thuban/UI/classgen.py:370
+msgid "Min:"
+msgstr "Minimum:"
+
+#: ../Thuban/UI/classgen.py:375
+msgid "Max:"
+msgstr "Maximum:"
+
+#: ../Thuban/UI/classgen.py:380 ../Thuban/UI/classgen.py:633
+msgid "Retrieve From Table"
+msgstr "Kigyûjt táblából"
+
+#: ../Thuban/UI/classgen.py:390
+msgid "Number of Groups:"
+msgstr "Csoportok száma:"
+
+#: ../Thuban/UI/classgen.py:397
+msgid "Stepping:"
+msgstr "Lépés:"
+
+#: ../Thuban/UI/classgen.py:647
+msgid "Available"
+msgstr "Elérhetõ"
+
+#: ../Thuban/UI/classgen.py:652 ../Thuban/UI/classgen.py:692
+msgid "Sort"
+msgstr "Rendez"
+
+#: ../Thuban/UI/classgen.py:655 ../Thuban/UI/classgen.py:695
+msgid "Reverse"
+msgstr "Vissza"
+
+#: ../Thuban/UI/classgen.py:687
+msgid "Use"
+msgstr "Használ"
+
+#: ../Thuban/UI/classgen.py:832
+msgid "Retrieve from Table"
+msgstr "Kigyûjt táblából"
+
+#: ../Thuban/UI/classgen.py:840
+msgid "Apply to Range"
+msgstr "Tartományhoz igazít"
+
+#: ../Thuban/UI/classgen.py:847
+msgid "Number of Classes:"
+msgstr "Osztályok száma:"
+
+#: ../Thuban/UI/classgen.py:930
+msgid "Start:"
+msgstr "Kezdet:"
+
+#: ../Thuban/UI/classgen.py:961
+msgid "End:"
+msgstr "Vég:"
+
+#: ../Thuban/UI/classifier.py:164
+msgid "The Default group cannot be removed."
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:309
+#: ../Thuban/UI/classifier.py:467
+msgid "Pattern"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:306
+#: ../Thuban/UI/classifier.py:466
+msgid "Singleton"
+msgstr "Singleton"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Visible"
+msgstr "Látható"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Symbol"
+msgstr "Szimbólum"
+
+#: ../Thuban/UI/classifier.py:317 ../Thuban/UI/controls.py:33
+#: ../Thuban/UI/controls.py:177
+msgid "Value"
+msgstr "Érték"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Label"
+msgstr "Címke"
+
+#: ../Thuban/UI/classifier.py:462 ../Thuban/UI/classifier.py:465
+msgid "Default"
+msgstr "Alapértelmezett"
+
+#: ../Thuban/UI/classifier.py:468
+msgid "Range"
+msgstr "Tartomány"
+
+#: ../Thuban/UI/classifier.py:469
+msgid "Map"
+msgstr "Térkép"
+
+#: ../Thuban/UI/classifier.py:759
+msgid "Text"
+msgstr "Szöveg"
+
+#: ../Thuban/UI/classifier.py:760
+msgid "Integer"
+msgstr "Egész szám"
+
+#: ../Thuban/UI/classifier.py:761
+msgid "Decimal"
+msgstr "Decimális"
+
+#: ../Thuban/UI/classifier.py:820
+msgid "Generate Class"
+msgstr "Osztálygenerálás"
+
+#: ../Thuban/UI/classifier.py:822 ../Thuban/UI/dbdialog.py:274
+msgid "Add"
+msgstr "Hozzáad"
+
+#: ../Thuban/UI/classifier.py:824
+msgid "Move Up"
+msgstr "Mozgatás fel"
+
+#: ../Thuban/UI/classifier.py:826
+msgid "Move Down"
+msgstr "Mozgatás le"
+
+#: ../Thuban/UI/classifier.py:828
+msgid "Edit Symbol"
+msgstr "Szimbólum beállítása"
+
+#: ../Thuban/UI/classifier.py:830 ../Thuban/UI/dbdialog.py:275
+#: ../Thuban/UI/projdialog.py:117
+msgid "Remove"
+msgstr "Töröl"
+
+#: ../Thuban/UI/classifier.py:845
+msgid "Field: "
+msgstr "Mezõ:"
+
+#: ../Thuban/UI/classifier.py:1000 ../Thuban/UI/layerproperties.py:160
+msgid "Layer Properties"
+msgstr "Réteg-tulajdonságok"
+
+#: ../Thuban/UI/classifier.py:1167
+msgid "Select Properties"
+msgstr "Tulajdonságok kiválasztása"
+
+#: ../Thuban/UI/classifier.py:1178
+msgid "Preview:"
+msgstr "Elõnézet:"
+
+#: ../Thuban/UI/classifier.py:1195
+msgid "Change Line Color"
+msgstr "Vonal színének megváltoztatása"
+
+#: ../Thuban/UI/classifier.py:1201 ../Thuban/UI/classifier.py:1216
+msgid "Transparent"
+msgstr "Átlátszó"
+
+#: ../Thuban/UI/classifier.py:1212
+msgid "Change Fill Color"
+msgstr "Kitöltõ szín beállítása"
+
+#: ../Thuban/UI/classifier.py:1225
+msgid "Line Width: "
+msgstr "Vonalvastagság:"
+
+#: ../Thuban/UI/classifier.py:1242
+msgid "Size: "
+msgstr "Méret:"
+
+#: ../Thuban/UI/classifier.py:1262 ../Thuban/UI/colordialog.py:52
+#: ../Thuban/UI/dbdialog.py:107 ../Thuban/UI/dbdialog.py:221
+#: ../Thuban/UI/labeldialog.py:41 ../Thuban/UI/layerproperties.py:81
+#: ../Thuban/UI/projdialog.py:205
+msgid "OK"
+msgstr "OK"
+
+#: ../Thuban/UI/classifier.py:1264 ../Thuban/UI/colordialog.py:53
+#: ../Thuban/UI/dbdialog.py:110 ../Thuban/UI/dbdialog.py:223
+#: ../Thuban/UI/labeldialog.py:42 ../Thuban/UI/projdialog.py:1033
+msgid "Cancel"
+msgstr "Mégsem"
+
+#: ../Thuban/UI/colordialog.py:39
+msgid "Select Color"
+msgstr "Szín kiválasztása"
+
+#: ../Thuban/UI/controls.py:31
+msgid "Field"
+msgstr "Mezõ"
+
+#: ../Thuban/UI/dbdialog.py:41
+msgid "Choose layer from database"
+msgstr "Réteg választása adatbázisból"
+
+#: ../Thuban/UI/dbdialog.py:59
+msgid "Databases"
+msgstr "Adatbázisok"
+
+#: ../Thuban/UI/dbdialog.py:74
+msgid "Retrieve"
+msgstr "Kigyûjt"
+
+#: ../Thuban/UI/dbdialog.py:82
+msgid "Tables"
+msgstr "Táblák"
+
+#: ../Thuban/UI/dbdialog.py:92
+msgid "ID Column"
+msgstr "Azonosító oszlop"
+
+#: ../Thuban/UI/dbdialog.py:98
+msgid "Geometry Column"
+msgstr "Geometrikus oszlop"
+
+#: ../Thuban/UI/dbdialog.py:187
+msgid "Hostname:"
+msgstr "Gazda:"
+
+#: ../Thuban/UI/dbdialog.py:191
+msgid "Port:"
+msgstr "Kapu:"
+
+#: ../Thuban/UI/dbdialog.py:198
+msgid "Database Name:"
+msgstr "Adatbázis neve:"
+
+#: ../Thuban/UI/dbdialog.py:206
+msgid "User:"
+msgstr "Felhasználó:"
+
+#: ../Thuban/UI/dbdialog.py:211
+msgid "Password:"
+msgstr "Jelszó:"
+
+#: ../Thuban/UI/dbdialog.py:286
+msgid "Database Management"
+msgstr "Adatbázis-kezelés"
+
+#: ../Thuban/UI/dbdialog.py:361 ../Thuban/UI/dbdialog.py:366
+msgid "Add Database"
+msgstr "Adatbázis hozzáadása"
+
+#: ../Thuban/UI/dbdialog.py:367
+#, python-format
+msgid "Connection '%s' already exists"
+msgstr "A '%s' kapcsolat már létezik"
+
+#: ../Thuban/UI/dbdialog.py:388
+msgid "Remove Database Connection"
+msgstr "Adatbázis-kapcsolat eltávolítása"
+
+#: ../Thuban/UI/dbdialog.py:389
+#, python-format
+msgid ""
+"The connection %s\n"
+"is still in use"
+msgstr ""
+"A kapcsolat %s\n"
+"még használatban van."
+
+#: ../Thuban/UI/dock.py:190
+msgid "Undock"
+msgstr "Felold"
+
+#: ../Thuban/UI/dock.py:218
+msgid "Dock"
+msgstr "Dokkol"
+
+#: ../Thuban/UI/exceptiondialog.py:23 ../Thuban/UI/exceptiondialog.py:61
+msgid "Thuban: Internal Error"
+msgstr "Thuban: Belsõ Hiba"
+
+#: ../Thuban/UI/exceptiondialog.py:43
+msgid "Proceed"
+msgstr "Tovább"
+
+#: ../Thuban/UI/exceptiondialog.py:44
+msgid "Exit Thuban now"
+msgstr "Kilépés a Thubanból most"
+
+#: ../Thuban/UI/extensionregistry.py:72
+msgid "Initialization not yet requested."
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:88
+msgid "Initialization successful."
+msgstr ""
+
+#: ../Thuban/UI/identifyview.py:44
+msgid "Identify Shape"
+msgstr "Alakzat azonosítása"
+
+#: ../Thuban/UI/identifyview.py:56
+msgid "Close Window"
+msgstr "Ablak bezárása"
+
+#: ../Thuban/UI/identifyview.py:57
+msgid "Stop Identify Mode"
+msgstr "Azonosító módot befejez"
+
+#: ../Thuban/UI/join.py:64
+msgid "Join"
+msgstr "Összekapcsolás"
+
+#: ../Thuban/UI/join.py:71 ../Thuban/UI/join.py:72
+msgid "Select..."
+msgstr "Kiválaszt..."
+
+#: ../Thuban/UI/join.py:100 ../Thuban/UI/join.py:108
+msgid "Table:"
+msgstr "Tábla:"
+
+#: ../Thuban/UI/join.py:111 ../Thuban/UI/join.py:114
+msgid "Field:"
+msgstr "Mezõ:"
+
+#: ../Thuban/UI/join.py:125
+msgid "Outer Join (preserves left table records)"
+msgstr "Külsõ illesztés (a bal tábla rekordjait megtartja)"
+
+#: ../Thuban/UI/join.py:173
+#, python-format
+msgid ""
+"Join failed:\n"
+"  %s"
+msgstr ""
+"Az összekapcsolás sikertelen:\n"
+" %s"
+
+#: ../Thuban/UI/join.py:174
+msgid "Info"
+msgstr "Információ"
+
+#: ../Thuban/UI/join.py:195
+#, python-format
+msgid ""
+"The joined table has %(joined)d rows but it must have %(needed)d rows to be "
+"used with the selected layer"
+msgstr ""
+"Az kapcsolt táblának %(joined)d sora van, de %(needed)d sorra van szükség a "
+"kijelölt réteggel való használatához"
+
+#: ../Thuban/UI/join.py:200
+msgid "Join Failed"
+msgstr "Az összekapcsolás sikertelen"
+
+#: ../Thuban/UI/join.py:209 ../Thuban/UI/mainwindow.py:915
+#, python-format
+msgid "Table: %s"
+msgstr "Tábla: %s"
+
+#: ../Thuban/UI/labeldialog.py:26
+msgid "Label Values"
+msgstr "Címke értékek"
+
+#: ../Thuban/UI/layerproperties.py:54
+msgid "Title: "
+msgstr "Cím: "
+
+#: ../Thuban/UI/layerproperties.py:65
+#, fuzzy, python-format
+msgid "Layer Type: %s"
+msgstr "Réteg-tábla: %s"
+
+#: ../Thuban/UI/layerproperties.py:71
+#, fuzzy
+msgid "Projection: None"
+msgstr "Vetület:"
+
+#: ../Thuban/UI/layerproperties.py:73
+#, fuzzy, python-format
+msgid "Projection: %s"
+msgstr "Vetület:"
+
+#: ../Thuban/UI/layerproperties.py:79 ../Thuban/UI/projdialog.py:199
+msgid "Try"
+msgstr "Próba"
+
+#: ../Thuban/UI/layerproperties.py:80 ../Thuban/UI/projdialog.py:202
+msgid "Revert"
+msgstr "Visszaállítás"
+
+#: ../Thuban/UI/legend.py:75
+msgid "Top Layer"
+msgstr "Legfelsõ réteg"
+
+#: ../Thuban/UI/legend.py:79
+msgid "Raise Layer"
+msgstr "Réteg feljebb"
+
+#: ../Thuban/UI/legend.py:83
+msgid "Lower Layer"
+msgstr "Réteg lejjebb"
+
+#: ../Thuban/UI/legend.py:87
+msgid "Bottom Layer"
+msgstr "Legalsó réteg"
+
+#: ../Thuban/UI/legend.py:91
+msgid "Show Layer"
+msgstr "Réteg megjelenítése"
+
+#: ../Thuban/UI/legend.py:95
+msgid "Hide Layer"
+msgstr "Réteg elrejtése"
+
+#: ../Thuban/UI/legend.py:99
+msgid "Edit Layer Properties"
+msgstr "Réteg tulajdonságainak szerkesztése"
+
+#: ../Thuban/UI/mainwindow.py:264 ../Thuban/UI/mainwindow.py:286
+#, python-format
+msgid "Unknown command %s"
+msgstr "Ismeretlen parancs %s"
+
+#: ../Thuban/UI/mainwindow.py:299
+#, python-format
+msgid "Unknown command ID %d"
+msgstr "Ismeretlen parancs ID %d"
+
+#: ../Thuban/UI/mainwindow.py:338
+#, python-format
+msgid "The Dialog named %s is already open"
+msgstr "A %s ablak már nyitva van"
+
+#: ../Thuban/UI/mainwindow.py:396
+#, python-format
+msgid "Select layer '%s' and pick a projection using Layer/Projection..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:449
+msgid "Exit"
+msgstr "Kilép"
+
+#: ../Thuban/UI/mainwindow.py:450
+msgid "The session has been modified. Do you want to save it?"
+msgstr "A munkafolymat neve megváltozott. Mentsük?"
+
+#: ../Thuban/UI/mainwindow.py:465
+msgid "Open Session"
+msgstr "Munkafolyamat megnyitása"
+
+#: ../Thuban/UI/mainwindow.py:487
+msgid "Save Session As"
+msgstr "Munkafolyamat mentése másként"
+
+#: ../Thuban/UI/mainwindow.py:561
+msgid "Select one or more data files"
+msgstr "Válasszon ki egy vagy több adatfájlt"
+
+#: ../Thuban/UI/mainwindow.py:576
+msgid "Add Layer"
+msgstr "Réteg hozzáadása"
+
+#: ../Thuban/UI/mainwindow.py:577 ../Thuban/UI/mainwindow.py:602
+#: ../Thuban/UI/mainwindow.py:862
+#, python-format
+msgid "Can't open the file '%s'."
+msgstr "Nem tudom megnyitni a(z) '%s' fájlt."
+
+#: ../Thuban/UI/mainwindow.py:589
+msgid "Select an image file"
+msgstr "Képfájl kiválasztása"
+
+#: ../Thuban/UI/mainwindow.py:601
+msgid "Add Image Layer"
+msgstr "Kép-réteg hozzáadása"
+
+#: ../Thuban/UI/mainwindow.py:629
+msgid "Add Layer from database"
+msgstr "Réteg hozzáadása adatbázisból"
+
+#: ../Thuban/UI/mainwindow.py:630
+#, python-format
+msgid "Can't open the database table '%s'"
+msgstr "A(z) '%s' adatbázis-táblát nem lehet megnyitni."
+
+#: ../Thuban/UI/mainwindow.py:719
+#, python-format
+msgid "Copy of `%s'"
+msgstr "`%s' másolása"
+
+#: ../Thuban/UI/mainwindow.py:749
+#, python-format
+msgid "Layer Table: %s"
+msgstr "Réteg-tábla: %s"
+
+#: ../Thuban/UI/mainwindow.py:764
+#, python-format
+msgid "Map Projection: %s"
+msgstr "Térkép vetülete: %s"
+
+#: ../Thuban/UI/mainwindow.py:779
+#, python-format
+msgid "Layer Projection: %s"
+msgstr "Réteg vetülete: %s"
+
+#: ../Thuban/UI/mainwindow.py:812
+msgid "Join Layer with Table"
+msgstr "Réteg összekapcsolása táblával"
+
+#: ../Thuban/UI/mainwindow.py:834 ../Thuban/UI/mainwindow.py:1165
+msgid "Legend"
+msgstr "Jelmagyarázat"
+
+#: ../Thuban/UI/mainwindow.py:848 ../Thuban/UI/mainwindow.py:861
+msgid "Open Table"
+msgstr "Tábla megnyitása"
+
+#: ../Thuban/UI/mainwindow.py:850
+msgid "DBF Files (*.dbf)"
+msgstr "DBF-fájlok(*.dbf)"
+
+#: ../Thuban/UI/mainwindow.py:873
+msgid "Pick the tables to close:"
+msgstr "Tábla kiválasztása bezárásra:"
+
+#: ../Thuban/UI/mainwindow.py:874
+msgid "Close Table"
+msgstr "Tábla bezárása"
+
+#: ../Thuban/UI/mainwindow.py:894
+msgid "Pick the table to show:"
+msgstr "Tábla kiválasztása megjelenítésre:"
+
+#: ../Thuban/UI/mainwindow.py:895
+msgid "Show Table"
+msgstr "Tábla mutat"
+
+#: ../Thuban/UI/mainwindow.py:906
+msgid "Join Tables"
+msgstr "Táblák összekapcsolása"
+
+#: ../Thuban/UI/mainwindow.py:929
+msgid "Pick the table to rename:"
+msgstr "Tábla kiválasztása átnevezésre:"
+
+#: ../Thuban/UI/mainwindow.py:930 ../Thuban/UI/mainwindow.py:942
+msgid "Rename Table"
+msgstr "Tábla átnevezése"
+
+#: ../Thuban/UI/mainwindow.py:942
+msgid "Table Title:"
+msgstr "Tábla címe:"
+
+#: ../Thuban/UI/mainwindow.py:991
+msgid "Map Title:"
+msgstr "Térkép címe:"
+
+#: ../Thuban/UI/mainwindow.py:991
+msgid "Rename Map"
+msgstr "Térkép átnevezése"
+
+#: ../Thuban/UI/mainwindow.py:1004
+msgid "Layer Title:"
+msgstr "Réteg címe:"
+
+#: ../Thuban/UI/mainwindow.py:1004
+msgid "Rename Layer"
+msgstr "Réteg átnevezése"
+
+#: ../Thuban/UI/mainwindow.py:1057
+#, python-format
+msgid "Thuban - %s"
+msgstr "Thuban - %s"
+
+#: ../Thuban/UI/mainwindow.py:1059
+msgid "Thuban"
+msgstr "Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1154
+msgid "&New Session"
+msgstr "Új mu&nkafolyamat"
+
+#: ../Thuban/UI/mainwindow.py:1155
+msgid "Start a new session"
+msgstr "Új munkafolyamat indul"
+
+#: ../Thuban/UI/mainwindow.py:1156
+msgid "&Open Session..."
+msgstr "Munkaf&olyamat megnyitása..."
+
+#: ../Thuban/UI/mainwindow.py:1157
+msgid "Open a session file"
+msgstr "Munkafolyamat-fájl megnyitása"
+
+#: ../Thuban/UI/mainwindow.py:1158
+msgid "&Save Session"
+msgstr "Munkafolyamat menté&se"
+
+#: ../Thuban/UI/mainwindow.py:1159
+msgid "Save this session to the file it was opened from"
+msgstr "Mentsed ezt a munkafolyamatot abba a fájlba, amibõl meg lett nyitva"
+
+#: ../Thuban/UI/mainwindow.py:1160
+msgid "Save Session &As..."
+msgstr "Munk&afolyamat mentése másként"
+
+#: ../Thuban/UI/mainwindow.py:1161
+msgid "Save this session to a new file"
+msgstr "Munkafolyamat mentése új fájlba"
+
+#: ../Thuban/UI/mainwindow.py:1162
+msgid "Session &Tree"
+msgstr "Munkafolyamat &története"
+
+#: ../Thuban/UI/mainwindow.py:1164
+msgid "Toggle on/off the session tree analysis window"
+msgstr "A munkafolyamat-fájának elmzésére szolgáló ablak ki/bekapcsolója"
+
+#: ../Thuban/UI/mainwindow.py:1167
+msgid "Toggle Legend on/off"
+msgstr "Segédszövegek ki- és bekapcsolása"
+
+#: ../Thuban/UI/mainwindow.py:1168
+msgid "&Database Connections..."
+msgstr "A&datbázis kapcsolatok"
+
+#: ../Thuban/UI/mainwindow.py:1171
+msgid "E&xit"
+msgstr "&Kilép"
+
+#: ../Thuban/UI/mainwindow.py:1172
+msgid "Finish working with Thuban"
+msgstr "A Thuban munkának befelyezése"
+
+#: ../Thuban/UI/mainwindow.py:1175
+msgid "&About..."
+msgstr "&Névjegy..."
+
+#: ../Thuban/UI/mainwindow.py:1176
+msgid "Info about Thuban authors, version and modules"
+msgstr "Információ a Thuban alkotóiról, verziójáról és moduljairól"
+
+#: ../Thuban/UI/mainwindow.py:1180 ../Thuban/UI/mainwindow.py:1228
+msgid "Pro&jection..."
+msgstr "&Vetület"
+
+#: ../Thuban/UI/mainwindow.py:1181
+msgid "Set or change the map projection"
+msgstr "A térkép vetületének beállítása"
+
+#: ../Thuban/UI/mainwindow.py:1183
+msgid "&Zoom in"
+msgstr "&Nagyítás"
+
+#: ../Thuban/UI/mainwindow.py:1184
+msgid "Switch to map-mode 'zoom-in'"
+msgstr "Nagyításra váltás"
+
+#: ../Thuban/UI/mainwindow.py:1186
+msgid "Zoom &out"
+msgstr "&Kicsinyítés"
+
+#: ../Thuban/UI/mainwindow.py:1187
+msgid "Switch to map-mode 'zoom-out'"
+msgstr "Kicsinyítésre váltás"
+
+#: ../Thuban/UI/mainwindow.py:1189
+msgid "&Pan"
+msgstr "&Mozgat"
+
+#: ../Thuban/UI/mainwindow.py:1190
+msgid "Switch to map-mode 'pan'"
+msgstr "Mozgatásra váltás"
+
+#: ../Thuban/UI/mainwindow.py:1192
+msgid "&Identify"
+msgstr "&Azonosít"
+
+#: ../Thuban/UI/mainwindow.py:1194
+msgid "Switch to map-mode 'identify'"
+msgstr "Azonosításra váltás"
+
+#: ../Thuban/UI/mainwindow.py:1196
+msgid "&Label"
+msgstr "&Címke"
+
+#: ../Thuban/UI/mainwindow.py:1197
+msgid "Add/Remove labels"
+msgstr "Címke hozzáadása/eltávolítása"
+
+#: ../Thuban/UI/mainwindow.py:1199
+msgid "&Full extent"
+msgstr "&Teljes terjedelem"
+
+#: ../Thuban/UI/mainwindow.py:1200
+msgid "Zoom to the full map extent"
+msgstr "Méretezés a térkép teljes kiterjedésére"
+
+#: ../Thuban/UI/mainwindow.py:1202
+msgid "&Full layer extent"
+msgstr "&Réteg teljes terjedelem"
+
+#: ../Thuban/UI/mainwindow.py:1203
+msgid "Zoom to the full layer extent"
+msgstr "Méretezés a réteg teljes kiterjedésére"
+
+#: ../Thuban/UI/mainwindow.py:1205
+msgid "&Full selection extent"
+msgstr "&Kijelölés teljes terjedelemben"
+
+#: ../Thuban/UI/mainwindow.py:1207
+msgid "Zoom to the full selection extent"
+msgstr "Méretezés a kijelöltek teljes kiterjedésére"
+
+#: ../Thuban/UI/mainwindow.py:1209
+msgid "E&xport"
+msgstr "E&xportálás..."
+
+#: ../Thuban/UI/mainwindow.py:1210
+msgid "Export the map to file"
+msgstr "Térkép exportálása fájlba"
+
+#: ../Thuban/UI/mainwindow.py:1211
+msgid "Prin&t"
+msgstr "&Nyomtat"
+
+#: ../Thuban/UI/mainwindow.py:1212
+msgid "Print the map"
+msgstr "Térkép nyomtatása"
+
+#: ../Thuban/UI/mainwindow.py:1213 ../Thuban/UI/mainwindow.py:1299
+msgid "&Rename..."
+msgstr "&Átnevez..."
+
+#: ../Thuban/UI/mainwindow.py:1214
+msgid "Rename the map"
+msgstr "Térkép átnevezése"
+
+#: ../Thuban/UI/mainwindow.py:1215
+msgid "&Add Layer..."
+msgstr "&Réteg hozzáadása"
+
+#: ../Thuban/UI/mainwindow.py:1216
+msgid "Add a new layer to the map"
+msgstr "Réteg hozzáadása a térképhez"
+
+#: ../Thuban/UI/mainwindow.py:1217
+msgid "&Add Image Layer..."
+msgstr "Kép-réteg hozzáadása..."
+
+#: ../Thuban/UI/mainwindow.py:1218
+msgid "Add a new image layer to the map"
+msgstr "Új kép-réteg hozzáadása a térképhez"
+
+#: ../Thuban/UI/mainwindow.py:1220
+msgid "Add &Database Layer..."
+msgstr "Adatbázis-réteg hozzáadása..."
+
+#: ../Thuban/UI/mainwindow.py:1221
+msgid "Add a new database layer to active map"
+msgstr "Az aktív térképhez új adatbázis-rteg hozzáadása"
+
+#: ../Thuban/UI/mainwindow.py:1223
+msgid "&Remove Layer"
+msgstr "&Réteg eltávolítása"
+
+#: ../Thuban/UI/mainwindow.py:1224
+msgid "Remove selected layer"
+msgstr "Kijelölt réteg eltávolítása"
+
+#: ../Thuban/UI/mainwindow.py:1230
+msgid "Specify projection for selected layer"
+msgstr "Határozza meg a kiválasztott réteg vetületét"
+
+#: ../Thuban/UI/mainwindow.py:1231
+msgid "&Duplicate"
+msgstr "&Kettõzés"
+
+#: ../Thuban/UI/mainwindow.py:1232
+msgid "Duplicate selected layer"
+msgstr "Kijelölt réteg megkettõzése"
+
+#: ../Thuban/UI/mainwindow.py:1234
+msgid "Re&name ..."
+msgstr "Át&nevezés"
+
+#: ../Thuban/UI/mainwindow.py:1235
+msgid "Rename selected layer"
+msgstr "Kijelölt réteg átnevezése"
+
+#: ../Thuban/UI/mainwindow.py:1237
+msgid "&Raise"
+msgstr "Fel&emelés"
+
+#: ../Thuban/UI/mainwindow.py:1238
+msgid "Raise selected layer"
+msgstr "Kijelölt réteg feljebb"
+
+#: ../Thuban/UI/mainwindow.py:1240
+msgid "&Lower"
+msgstr "&Lejjebb"
+
+#: ../Thuban/UI/mainwindow.py:1241
+msgid "Lower selected layer"
+msgstr "Kijeölt réteg lejjedd"
+
+#: ../Thuban/UI/mainwindow.py:1243
+msgid "&Show"
+msgstr "Meg&jelenítés"
+
+#: ../Thuban/UI/mainwindow.py:1244
+msgid "Make selected layer visible"
+msgstr "A kijelölt réteg látható"
+
+#: ../Thuban/UI/mainwindow.py:1246
+msgid "&Hide"
+msgstr "El&rejtés"
+
+#: ../Thuban/UI/mainwindow.py:1247
+msgid "Make selected layer unvisible"
+msgstr "Kiválasztott réteg elfedése"
+
+#: ../Thuban/UI/mainwindow.py:1249
+msgid "Show Ta&ble"
+msgstr "Tá&bla mutat"
+
+#: ../Thuban/UI/mainwindow.py:1250
+msgid "Show the selected layer's table"
+msgstr "A kijelölt réteg tábláját mutat"
+
+#: ../Thuban/UI/mainwindow.py:1252
+msgid "&Properties..."
+msgstr "&Tulajdonságok..."
+
+#: ../Thuban/UI/mainwindow.py:1254
+msgid "Edit the properties of the selected layer"
+msgstr "A kijelölt réteg jellemzõinek szerkesztése."
+
+#: ../Thuban/UI/mainwindow.py:1255
+msgid "&Join Table..."
+msgstr "Tábla össz&ekapcsolás..."
+
+#: ../Thuban/UI/mainwindow.py:1257
+msgid "Join and attach a table to the selected layer"
+msgstr "A kiválasztott réteghez tábla illesztése és kapcsolása"
+
+#: ../Thuban/UI/mainwindow.py:1260
+msgid "&Top"
+msgstr "&Legfelsõ"
+
+#: ../Thuban/UI/mainwindow.py:1261
+msgid "Put selected layer to the top"
+msgstr "Kijelölt réteget a tetejére"
+
+#: ../Thuban/UI/mainwindow.py:1263
+msgid "&Bottom"
+msgstr "&Alap"
+
+#: ../Thuban/UI/mainwindow.py:1264
+msgid "Put selected layer to the bottom"
+msgstr "Kijelölt réteget a legalulra"
+
+#: ../Thuban/UI/mainwindow.py:1266
+msgid "&Visible"
+msgstr "&Látható"
+
+#: ../Thuban/UI/mainwindow.py:1268
+msgid "Toggle visibility of selected layer"
+msgstr "A kijelölt réteg láthatóságának kapcsolója?"
+
+#: ../Thuban/UI/mainwindow.py:1285
+msgid "&Unjoin Table..."
+msgstr "Tábla le&választása..."
+
+#: ../Thuban/UI/mainwindow.py:1287
+msgid "Undo the last join operation"
+msgstr "Az utolsó összekapcsolási mûvelet visszavonása"
+
+#: ../Thuban/UI/mainwindow.py:1294
+msgid "&Open..."
+msgstr "&Megnyit..."
+
+#: ../Thuban/UI/mainwindow.py:1295
+msgid "Open a DBF-table from a file"
+msgstr "Egy DBF-fájl megnyitása fájlból"
+
+#: ../Thuban/UI/mainwindow.py:1296
+msgid "&Close..."
+msgstr "&Bezár..."
+
+#: ../Thuban/UI/mainwindow.py:1298
+msgid "Close one or more tables from a list"
+msgstr "Egy vagy több tábla bezárása a listából"
+
+#: ../Thuban/UI/mainwindow.py:1301
+msgid "Rename one or more tables"
+msgstr "Egy vagy több tábla átnevezése"
+
+#: ../Thuban/UI/mainwindow.py:1302
+msgid "&Show..."
+msgstr "&Megjelenít..."
+
+#: ../Thuban/UI/mainwindow.py:1304
+msgid "Show one or more tables in a dialog"
+msgstr "Egy vagy több tábla mutatása..."
+
+#: ../Thuban/UI/mainwindow.py:1305
+msgid "&Join..."
+msgstr "&Kapcsolódás..."
+
+#: ../Thuban/UI/mainwindow.py:1307
+msgid "Join two tables creating a new one"
+msgstr "Két összekapcsolt tábla egy újat eredményez"
+
+#: ../Thuban/UI/mainwindow.py:1331
+msgid "&File"
+msgstr "&Fájl"
+
+#: ../Thuban/UI/mainwindow.py:1337
+msgid "&Map"
+msgstr "&Térkép"
+
+#: ../Thuban/UI/mainwindow.py:1338
+msgid "&Layer"
+msgstr "&Réteg"
+
+#: ../Thuban/UI/mainwindow.py:1352
+msgid "&Table"
+msgstr "&Táblázat"
+
+#: ../Thuban/UI/mainwindow.py:1358
+msgid "&Help"
+msgstr "&Súgó"
+
+#: ../Thuban/UI/menu.py:90
+#, python-format
+msgid "Submenu %s doesn't exist"
+msgstr "A(z) '%s' almenû nem létezik"
+
+#: ../Thuban/UI/projdialog.py:62 ../Thuban/UI/projdialog.py:776
+msgid "Transverse Mercator"
+msgstr "Transverse Mercator"
+
+#: ../Thuban/UI/projdialog.py:63 ../Thuban/UI/projdialog.py:842
+msgid "Universal Transverse Mercator"
+msgstr "Universal Transverse Mercator"
+
+#: ../Thuban/UI/projdialog.py:64 ../Thuban/UI/projdialog.py:918
+msgid "Lambert Conic Conformal"
+msgstr "Lambert féle kúpszeletes"
+
+#: ../Thuban/UI/projdialog.py:65 ../Thuban/UI/projdialog.py:66
+#: ../Thuban/UI/projdialog.py:968
+msgid "Geographic"
+msgstr "Földrajzi"
+
+#: ../Thuban/UI/projdialog.py:110
+msgid "Import..."
+msgstr "Importálás..."
+
+#: ../Thuban/UI/projdialog.py:113
+msgid "Export..."
+msgstr "Exportálás..."
+
+#: ../Thuban/UI/projdialog.py:122
+msgid "Show EPSG:"
+msgstr "EPSG mutat:"
+
+#: ../Thuban/UI/projdialog.py:124
+msgid "Normal"
+msgstr "Normál"
+
+#: ../Thuban/UI/projdialog.py:127
+msgid "Deprecated"
+msgstr "Érvénytelenített"
+
+#: ../Thuban/UI/projdialog.py:138
+msgid "Edit"
+msgstr "Szerkesztés"
+
+#: ../Thuban/UI/projdialog.py:148
+msgid "Name:"
+msgstr "Név:"
+
+#: ../Thuban/UI/projdialog.py:156
+msgid "Projection:"
+msgstr "Vetület:"
+
+#: ../Thuban/UI/projdialog.py:167 ../Thuban/UI/projdialog.py:648
+msgid "<Unknown>"
+msgstr "<ismeretlen>"
+
+#: ../Thuban/UI/projdialog.py:183
+msgid "New"
+msgstr "Új"
+
+#: ../Thuban/UI/projdialog.py:186
+msgid "Add to List"
+msgstr "Hozzáadás a listához"
+
+#: ../Thuban/UI/projdialog.py:190
+msgid "Update"
+msgstr "Frissítés"
+
+#: ../Thuban/UI/projdialog.py:295
+#, python-format
+msgid ""
+"Warnings when reading \"%s\":\n"
+"\n"
+"%s"
+msgstr ""
+"Fájlbeolvasási hiba \"%s\":\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/projdialog.py:306
+msgid "Import"
+msgstr "Importálás"
+
+#: ../Thuban/UI/projdialog.py:319 ../Thuban/UI/projdialog.py:617
+msgid "Warnings"
+msgstr "Figyelmeztetések"
+
+#: ../Thuban/UI/projdialog.py:337 ../Thuban/UI/tableview.py:386
+msgid "Export"
+msgstr "Exportálás"
+
+#: ../Thuban/UI/projdialog.py:389
+msgid "The following error occured:\n"
+msgstr "A következõ hiba történt:\n"
+
+#: ../Thuban/UI/projdialog.py:391
+msgid "Error"
+msgstr "Hiba"
+
+#: ../Thuban/UI/projdialog.py:460
+msgid "No Projections selected"
+msgstr "Nem lett kiválasztva vetület"
+
+#: ../Thuban/UI/projdialog.py:470
+#, python-format
+msgid "Source of Projection: %s"
+msgstr "Vetület forrása: %s"
+
+#: ../Thuban/UI/projdialog.py:502
+msgid "Multiple Projections selected"
+msgstr "Több vetülett lett kiválasztva"
+
+#: ../Thuban/UI/projdialog.py:649
+msgid "Airy"
+msgstr "Airy"
+
+#: ../Thuban/UI/projdialog.py:650
+msgid "Bessel 1841"
+msgstr "Bessel 1841"
+
+#: ../Thuban/UI/projdialog.py:651
+msgid "Clarke 1866"
+msgstr "Clarke 1866"
+
+#: ../Thuban/UI/projdialog.py:652
+msgid "Clarke 1880"
+msgstr "Clarke 1880"
+
+#: ../Thuban/UI/projdialog.py:653
+msgid "GRS 1980 (IUGG, 1980)"
+msgstr "GRS 1980 (IUGG, 1980)"
+
+#: ../Thuban/UI/projdialog.py:654
+msgid "International 1909 (Hayford)"
+msgstr "International 1909 (Hayford)"
+
+#: ../Thuban/UI/projdialog.py:655
+msgid "WGS 84"
+msgstr "WGS 84"
+
+#: ../Thuban/UI/projdialog.py:667
+msgid "Ellipsoid:"
+msgstr "Ellipszoid:"
+
+#: ../Thuban/UI/projdialog.py:716
+msgid ""
+"Thuban does not know the parameters\n"
+"for the current projection and cannot\n"
+"display a configuration panel.\n"
+"\n"
+"The unidentified set of parameters is:\n"
+"\n"
+msgstr ""
+"A Thuban nem ismeri a jelenlegi vetület\n"
+"paramétereit és nem tudja megjeleníteni\n"
+"a konfigurációs panelt.\n"
+"\n"
+"A paraméterek nem azonosított készlete:\n"
+"\n"
+
+#: ../Thuban/UI/projdialog.py:762
+msgid "Latitude:"
+msgstr "Szélesség:"
+
+#: ../Thuban/UI/projdialog.py:764
+msgid "Longitude:"
+msgstr "Hosszúság:"
+
+#: ../Thuban/UI/projdialog.py:766 ../Thuban/UI/projdialog.py:910
+msgid "False Easting:"
+msgstr "A középpont keleti irányú koordinátája:"
+
+#: ../Thuban/UI/projdialog.py:768 ../Thuban/UI/projdialog.py:912
+msgid "False Northing:"
+msgstr "A középpont északi irányú koordinátája:"
+
+#: ../Thuban/UI/projdialog.py:770
+msgid "Scale Factor:"
+msgstr "Skála tényezõ:"
+
+#: ../Thuban/UI/projdialog.py:821
+msgid "Propose"
+msgstr "Ajánlat"
+
+#: ../Thuban/UI/projdialog.py:823
+msgid "Southern Hemisphere"
+msgstr "Déli félteke"
+
+#: ../Thuban/UI/projdialog.py:833
+msgid "Zone:"
+msgstr "Zóna:"
+
+#: ../Thuban/UI/projdialog.py:870
+msgid "Can not propose: No bounding box found."
+msgstr "Nincs ajánlat: Nem található határoló doboz."
+
+#: ../Thuban/UI/projdialog.py:871 ../Thuban/UI/projdialog.py:1008
+msgid "Projection: Propose UTM Zone"
+msgstr "Vetület: javasolt UTM Zóna"
+
+#: ../Thuban/UI/projdialog.py:901
+msgid "Latitude of first standard parallel:"
+msgstr "Az elsõ standard párhuzamos szélessége:"
+
+#: ../Thuban/UI/projdialog.py:904
+msgid "Latitude of second standard parallel:"
+msgstr "A második standard párhuzamos szélessége:"
+
+#: ../Thuban/UI/projdialog.py:906
+msgid "Central Meridian:"
+msgstr "Centralis Meridián:"
+
+#: ../Thuban/UI/projdialog.py:908
+msgid "Latitude of origin:"
+msgstr "Szélesség:"
+
+#: ../Thuban/UI/projdialog.py:958
+msgid "Degrees"
+msgstr "Fok"
+
+#: ../Thuban/UI/projdialog.py:959
+msgid "Radians"
+msgstr "Radián"
+
+#: ../Thuban/UI/projdialog.py:992
+msgid "Source Data is in: "
+msgstr "A forrásadat:"
+
+#: ../Thuban/UI/projdialog.py:1021
+msgid "The current map extent center lies in UTM Zone"
+msgstr "Az aktuális térkép kiterjedésének közepe UTM Zónába esik"
+
+#: ../Thuban/UI/projdialog.py:1031
+msgid "Take"
+msgstr "Vidd"
+
+#: ../Thuban/UI/projlist.py:51
+msgid "Available Projections"
+msgstr "Elérhetõ vetületek"
+
+#: ../Thuban/UI/projlist.py:112
+msgid "<None>"
+msgstr "<semmi>"
+
+#: ../Thuban/UI/projlist.py:117
+#, python-format
+msgid "%s (current)"
+msgstr "%s (jelenlegi) "
+
+#: ../Thuban/UI/rasterlayerproperties.py:41
+msgid "GDAL image information unavailable. See About box for details."
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:49
+#, fuzzy
+msgid "Extent (lat-lon): None"
+msgstr "Kiterjedés (szélesség-hosszúság): "
+
+#: ../Thuban/UI/rasterlayerproperties.py:56
+#, fuzzy
+msgid "Image Properties"
+msgstr "Réteg-tulajdonságok"
+
+#: ../Thuban/UI/rasterlayerproperties.py:61
+#, python-format
+msgid "Source: %s"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:71
+#, fuzzy, python-format
+msgid "Driver: %s"
+msgstr "Mezõ: %s"
+
+#: ../Thuban/UI/rasterlayerproperties.py:74
+#, fuzzy, python-format
+msgid "Size: %ix%i"
+msgstr "Méret:"
+
+#: ../Thuban/UI/rasterlayerproperties.py:77
+#, fuzzy, python-format
+msgid "Number of Bands: %i"
+msgstr "Osztályok száma:"
+
+#: ../Thuban/UI/rasterlayerproperties.py:93
+msgid "Mask Type"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:99
+msgid "Opacity:"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:381
+msgid "Replace Selection"
+msgstr "Kijelölés megszüntetése"
+
+#: ../Thuban/UI/tableview.py:382
+msgid "Refine Selection"
+msgstr "Kijelölés finomítása"
+
+#: ../Thuban/UI/tableview.py:383
+msgid "Add to Selection"
+msgstr "Hozzáadás a kijelöléshez"
+
+#: ../Thuban/UI/tableview.py:385
+msgid "Query"
+msgstr "Lekérdezés"
+
+#: ../Thuban/UI/tableview.py:387
+msgid "Export Selection"
+msgstr "Kijelöltek exportálása"
+
+#: ../Thuban/UI/tableview.py:413
+msgid "Selection"
+msgstr "Kijelölés"
+
+#: ../Thuban/UI/tableview.py:455
+#, python-format
+msgid "%i rows (%i selected), %i columns"
+msgstr "%i sor (%i kijelölt), %i oszlop"
+
+#: ../Thuban/UI/tableview.py:535
+msgid "Export Table To"
+msgstr "Tábla exportálása"
+
+#: ../Thuban/UI/tableview.py:536
+msgid "DBF Files (*.dbf)|*.dbf|"
+msgstr "DBF-fájlok(*.dbf)|*.dbf|"
+
+#: ../Thuban/UI/tableview.py:537
+msgid "CSV Files (*.csv)|*.csv|"
+msgstr "CSV-fájlok (*.csv)|*.csv|"
+
+#: ../Thuban/UI/tableview.py:538
+msgid "All Files (*.*)|*.*"
+msgstr "Minden fájlt (*.*)|*.*"
+
+#: ../Thuban/UI/tree.py:226
+msgid "Session"
+msgstr "Munkafolyamat"
+
+#: ../Thuban/UI/view.py:285
+msgid "Export Map"
+msgstr "Térkép exportálása"
+
+#~ msgid "Type: %s"
+#~ msgstr "Típus: %s"

Added: packages/thuban/branches/upstream/current/po/it.po
===================================================================
--- packages/thuban/branches/upstream/current/po/it.po	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/po/it.po	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1869 @@
+# Italian Translations for Thuban
+# Copyright (C) 2003 Maurizio Napolitano.
+# Maurizio Napolitano <napo at itc.it>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: it\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-03-13 20:15+0000\n"
+"PO-Revision-Date: 2003-12-22 23:09+0100\n"
+"Last-Translator: Maurizio Napolitano <napo at itc.it>\n"
+"Language-Team:  <thuban at intevation.de>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.0.2\n"
+
+#: ../Thuban/version.py:189
+#, python-format
+msgid "%s %s < %s"
+msgstr "%s %s < %s"
+
+#: ../Thuban/version.py:195
+#, python-format
+msgid "Thuban was compiled with wx %(wxproj-wx)s but wxPython is %(wxPython)s"
+msgstr ""
+
+#: ../Thuban/Lib/connector.py:65
+#, python-format
+msgid "no receivers for channel %s of %s"
+msgstr "nessun ricevente per il canale %s di %s"
+
+#: ../Thuban/Lib/connector.py:70
+#, python-format
+msgid "receiver %s%s is not connected to channel %s of %s"
+msgstr "Il ricevente %s%s non è connesso al canale %s di %s"
+
+#: ../Thuban/Lib/connector.py:94
+#, python-format
+msgid "Warning: %s.%s: %s%s\n"
+msgstr "Attenzione: %s.%s: %s%s\n"
+
+#: ../Thuban/Lib/connector.py:118
+#, python-format
+msgid "\tmethod %s of %s"
+msgstr "\tmetodo %s di %s"
+
+#: ../Thuban/Lib/fileutil.py:87 ../Thuban/Lib/fileutil.py:141
+msgid "first argument must be an absolute filename"
+msgstr "Il primo argomento deve essere un nome di file univoco"
+
+#: ../Thuban/Lib/fileutil.py:138
+msgid "Both parameters must have a drive letter"
+msgstr "Entrambi i parametri devono avere una lettera di unità"
+
+#: ../Thuban/Lib/fileutil.py:198
+msgid "No implementation of get_application_dir available for platform"
+msgstr ""
+"Nessuna implementazione per get_application_dir disponibile per questa "
+"piattaforma"
+
+#: ../Thuban/Lib/fileutil.py:208
+msgid "No implementation of relative_filename available for platform"
+msgstr ""
+"Nessuna implementazione per relative_filename disponibile per questa "
+"piattaforma"
+
+#: ../Thuban/Model/classgen.py:338
+msgid "invalid index"
+msgstr "indice non valido"
+
+#: ../Thuban/Model/classification.py:309 ../Thuban/UI/classifier.py:758
+msgid "None"
+msgstr "Nessuno"
+
+#: ../Thuban/Model/classification.py:325
+msgid "Line Color"
+msgstr "Colore linea"
+
+#: ../Thuban/Model/classification.py:327
+#, python-format
+msgid "Line Width: %s"
+msgstr "Dimensione linea: %s"
+
+#: ../Thuban/Model/classification.py:333
+#, fuzzy, python-format
+msgid "Size: %s"
+msgstr "Campo: %s"
+
+#: ../Thuban/Model/classification.py:336
+msgid "Fill"
+msgstr "Riempimento"
+
+#: ../Thuban/Model/classification.py:342 ../Thuban/UI/classifier.py:841
+msgid "Classification"
+msgstr "Classificazione"
+
+#: ../Thuban/Model/classification.py:436
+msgid "lineWidth < 1"
+msgstr "dimensione linea < 1"
+
+#: ../Thuban/Model/classification.py:451
+msgid "size < 1"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:656 ../Thuban/UI/classifier.py:528
+msgid "DEFAULT"
+msgstr "PREDEFINITO"
+
+#: ../Thuban/Model/data.py:316
+msgid "Table not compatible with shapestore."
+msgstr "Tabella non compatibile con l'archivio del vettoriale"
+
+#: ../Thuban/Model/extension.py:90
+#, python-format
+msgid "Extension: %s"
+msgstr "Estensione: %s"
+
+#: ../Thuban/Model/label.py:91
+#, fuzzy, python-format
+msgid "Number of labels: %d"
+msgstr "Numero di classi:"
+
+#: ../Thuban/Model/label.py:92
+#, fuzzy, python-format
+msgid "Label Layer: %s"
+msgstr "Tabella: %s"
+
+#: ../Thuban/Model/layer.py:298 ../Thuban/Model/layer.py:566
+#: ../Thuban/Model/session.py:432
+#, python-format
+msgid "Filename: %s"
+msgstr "Nome file: %s"
+
+#: ../Thuban/Model/layer.py:301 ../Thuban/Model/layer.py:569
+msgid "Shown"
+msgstr "Visualizzato"
+
+#: ../Thuban/Model/layer.py:303 ../Thuban/Model/layer.py:571
+msgid "Hidden"
+msgstr "Nascosto"
+
+#: ../Thuban/Model/layer.py:304
+#, python-format
+msgid "Shapes: %d"
+msgstr "Vettoriali: %d"
+
+#: ../Thuban/Model/layer.py:308 ../Thuban/Model/layer.py:575
+#: ../Thuban/Model/map.py:287 ../Thuban/UI/rasterlayerproperties.py:51
+#, python-format
+msgid "Extent (lat-lon): (%g, %g, %g, %g)"
+msgstr "Estensione (lat-lon): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/layer.py:310 ../Thuban/Model/layer.py:577
+msgid "Extent (lat-lon):"
+msgstr "Estensione (lat-lon):"
+
+#: ../Thuban/Model/layer.py:311
+#, python-format
+msgid "Shapetype: %s"
+msgstr "Tipo vettoriale: %s"
+
+#: ../Thuban/Model/layer.py:314 ../Thuban/Model/layer.py:580
+#: ../Thuban/Model/map.py:292
+msgid "Projection"
+msgstr "Proiezione"
+
+#: ../Thuban/Model/layer.py:319 ../Thuban/Model/layer.py:583
+#, python-format
+msgid "Layer '%s'"
+msgstr "Livello '%s'"
+
+#: ../Thuban/Model/load.py:78
+#, python-format
+msgid "Invalid hexadecimal color specification %s"
+msgstr "Valore esadecimale del colore errato %s"
+
+#: ../Thuban/Model/load.py:81
+#, python-format
+msgid "Invalid color specification %s"
+msgstr "Errato valore di colore %s"
+
+#: ../Thuban/Model/load.py:544
+msgid "xml field type differs from database!"
+msgstr "il campo XML differisce da quello del database"
+
+#: ../Thuban/Model/load.py:609
+msgid "Classification range is not a number!"
+msgstr "La gamma di classificazione non è un numero!"
+
+#: ../Thuban/Model/map.py:53
+msgid "Labels"
+msgstr "Etichette"
+
+#: ../Thuban/Model/map.py:290
+#, python-format
+msgid "Extent (projected): (%g, %g, %g, %g)"
+msgstr "Estensione (proiettata): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/map.py:301
+#, python-format
+msgid "Map: %s"
+msgstr "Mappa: %s"
+
+#: ../Thuban/Model/proj.py:84 ../Thuban/Model/resource.py:179
+msgid "Unknown"
+msgstr "Sconosciuto"
+
+#: ../Thuban/Model/resource.py:46
+#, python-format
+msgid ""
+"No GDAL support because module '%s' cannot be imported. Python exception: '%"
+"s'"
+msgstr ""
+"Nessun supporto GDAL in quanto il modulo '%s' non può essere importato. "
+"Eccezione python: '%s'"
+
+#: ../Thuban/Model/resource.py:135 ../Thuban/Model/resource.py:155
+#, python-format
+msgid "Could not read \"%s\": %s"
+msgstr "Impossibile leggere \"%s\": %s"
+
+#: ../Thuban/Model/resource.py:187
+#, python-format
+msgid "Error in projection \"%s\": %s"
+msgstr "Errore nella proiezione \"%s\": %s"
+
+#: ../Thuban/Model/save.py:352
+msgid "Unsupported group type in classification"
+msgstr "Gruppo di classificazione non supportato"
+
+#: ../Thuban/Model/session.py:430
+msgid "Filename:"
+msgstr "Nome file:"
+
+#: ../Thuban/Model/session.py:435
+msgid "Modified"
+msgstr "Modificato"
+
+#: ../Thuban/Model/session.py:437
+msgid "Unmodified"
+msgstr "Non modificato"
+
+#: ../Thuban/Model/session.py:442
+#, python-format
+msgid "Session: %s"
+msgstr "Sessione: %s"
+
+#: ../Thuban/Model/session.py:448
+msgid "unnamed session"
+msgstr "sessione senza nome"
+
+#: ../Thuban/Model/session.py:450
+msgid "unnamed map"
+msgstr "mappa senza nome"
+
+#: ../Thuban/UI/about.py:28
+msgid "About Thuban"
+msgstr "Informazioni su Thuban"
+
+#: ../Thuban/UI/about.py:47
+msgid "French"
+msgstr "Francese"
+
+#: ../Thuban/UI/about.py:48
+msgid "German"
+msgstr "Tedesco"
+
+#: ../Thuban/UI/about.py:50
+msgid "Hungarian"
+msgstr ""
+
+#: ../Thuban/UI/about.py:51
+msgid "Italian"
+msgstr "Italiano"
+
+#: ../Thuban/UI/about.py:52
+msgid "Portuguese (Brazilian)"
+msgstr ""
+
+#: ../Thuban/UI/about.py:53
+msgid "Russian"
+msgstr "Russo"
+
+#: ../Thuban/UI/about.py:54
+msgid "Spanish"
+msgstr "Spagnolo"
+
+#: ../Thuban/UI/about.py:63 ../Thuban/UI/about.py:65 ../Thuban/UI/about.py:67
+msgid "- not available"
+msgstr "- non disponibile"
+
+#: ../Thuban/UI/about.py:72
+msgid "Currently using:\n"
+msgstr "Attualmente in uso:\n"
+
+#: ../Thuban/UI/about.py:78
+#, python-format
+msgid "\tInternal encoding: %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:84
+msgid "Compiled for:\n"
+msgstr "Compilato per:\n"
+
+#: ../Thuban/UI/about.py:90
+#, fuzzy
+msgid "Extensions:\n"
+msgstr "Estensione: %s"
+
+#: ../Thuban/UI/about.py:95 ../Thuban/UI/about.py:144
+msgid "\tNone registered.\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:98
+msgid "Maintainers:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:103
+msgid "Lead Developer:\n"
+msgstr "Sviluppatore capo: \n"
+
+#: ../Thuban/UI/about.py:106
+msgid "Developers:\n"
+msgstr "Sviluppatori:\n"
+
+#: ../Thuban/UI/about.py:111
+msgid "Translators:\n"
+msgstr "Traduttori:\n"
+
+#: ../Thuban/UI/about.py:116
+msgid "Other Contributors:\n"
+msgstr "Altri collaboratori:\n"
+
+#: ../Thuban/UI/about.py:122
+#, fuzzy
+msgid ""
+"Questions and comments can be sent to the following addresses:\n"
+"\tGeneral list (public):\n"
+"\t\t<thuban-list at intevation.de>\n"
+"\tDevelopers list (public):\n"
+"\t\t<thuban-devel at intevation.de>\n"
+"\tThuban team at Intevation:\n"
+"\t\t<thuban at intevation.de>\n"
+msgstr ""
+"Domande e commenti possono essere spediti ai seguenti indirizzi:\n"
+"\tSviluppatori Thuban:\n"
+"\t\t<thuban at intevation.de>\n"
+"\tThuban mailing list:\n"
+"\t\t<thuban-list at intevation.de>"
+
+#: ../Thuban/UI/about.py:130
+msgid ""
+"Details on the registered extensions:\n"
+"\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:135
+#, python-format
+msgid "Copyright %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:136
+msgid "Authors:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:149
+msgid ""
+"Thuban is a program for exploring geographic data.\n"
+"\n"
+msgstr ""
+"Thuban è un programma per esplorare dati geografici.\n"
+"\n"
+
+#: ../Thuban/UI/about.py:151
+msgid "Thuban is licensed under the GNU GPL"
+msgstr "Thuban è distribuito sotto licenza GNU GPL"
+
+#: ../Thuban/UI/about.py:160 ../Thuban/UI/classgen.py:91
+#: ../Thuban/UI/dbdialog.py:276 ../Thuban/UI/dock.py:371
+#: ../Thuban/UI/join.py:66 ../Thuban/UI/layerproperties.py:82
+#: ../Thuban/UI/projdialog.py:209 ../Thuban/UI/tableview.py:388
+msgid "Close"
+msgstr "Chiudi"
+
+#: ../Thuban/UI/altpathdialog.py:24
+#, fuzzy, python-format
+msgid "Select an alternative data file for %s"
+msgstr "Selezione uno o più file di dati"
+
+#: ../Thuban/UI/altpathdialog.py:31 ../Thuban/UI/mainwindow.py:563
+msgid "Shapefiles (*.shp)"
+msgstr "File shape (*.shp)"
+
+#: ../Thuban/UI/altpathdialog.py:32 ../Thuban/UI/mainwindow.py:564
+#: ../Thuban/UI/mainwindow.py:852
+msgid "All Files (*.*)"
+msgstr "Tutti i file (*.*)"
+
+#: ../Thuban/UI/altpathdialog.py:47
+#, python-format
+msgid ""
+"Found the following as an alternative for %s.\n"
+"%s\n"
+"\n"
+" Please confirm with Yes or select alternative with No."
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:49
+msgid "Alternative Path"
+msgstr ""
+
+#: ../Thuban/UI/application.py:110 ../Thuban/UI/application.py:122
+msgid "Cannot import the thubanstart module\n"
+msgstr "Impossibile importare il modulo thubanstart\n"
+
+#: ../Thuban/UI/application.py:115
+msgid "No thubanstart module available\n"
+msgstr "Nessun modulo thubanstart disponibile\n"
+
+#: ../Thuban/UI/application.py:126
+msgid "No ~/.thuban directory\n"
+msgstr "Directory ~/.thuban inesistente\n"
+
+#: ../Thuban/UI/application.py:166
+msgid ""
+"This is the wxPython-based Graphical User Interface for exploring geographic "
+"data"
+msgstr ""
+"Thuban: l'interfaccia grafica per visualizzare i dati geografici basata su "
+"wxPython"
+
+#: ../Thuban/UI/application.py:254
+msgid ""
+"The current session contains Image layers,\n"
+"but the GDAL library is not available to draw them."
+msgstr ""
+"La sessione corrente fa uso di livelli immagine,\n"
+"ma la libreria GDAL non è disponibile per visualizzarli."
+
+#: ../Thuban/UI/application.py:259
+msgid "Library not available"
+msgstr "Libreria non disponibile"
+
+#: ../Thuban/UI/application.py:268 ../Thuban/UI/mainwindow.py:476
+msgid "DB Connection Parameters"
+msgstr "Parametri di connessione al DB"
+
+#: ../Thuban/UI/application.py:364
+#, python-format
+msgid ""
+"An unhandled exception occurred:\n"
+"%s\n"
+"(please report to http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+msgstr ""
+"Si è verificata una eccezione non prevista:\n"
+"%s\n"
+"(per piacere segnala l'errore a http://thuban.intevation.org/bugtracker."
+"html)\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/classgen.py:43
+msgid "Uniform Distribution"
+msgstr "Distribuzione uniforme"
+
+#: ../Thuban/UI/classgen.py:44
+msgid "Unique Values"
+msgstr "Valori univoci"
+
+#: ../Thuban/UI/classgen.py:45
+msgid "Quantiles from Table"
+msgstr "Quantili per la tabella"
+
+#: ../Thuban/UI/classgen.py:47
+msgid "Custom Ramp"
+msgstr "Scala personalizzata"
+
+#: ../Thuban/UI/classgen.py:48
+msgid "Grey Ramp"
+msgstr "Scala di grigi"
+
+#: ../Thuban/UI/classgen.py:49
+msgid "Red Ramp"
+msgstr "Scala di rossi"
+
+#: ../Thuban/UI/classgen.py:50
+msgid "Green Ramp"
+msgstr "Scala di verdi"
+
+#: ../Thuban/UI/classgen.py:51
+msgid "Blue Ramp"
+msgstr "Scala di blu"
+
+#: ../Thuban/UI/classgen.py:52
+msgid "Green-to-Red Ramp"
+msgstr "Scala da verde a rossa"
+
+#: ../Thuban/UI/classgen.py:53
+msgid "Hot-to-Cold Ramp"
+msgstr "Scala da freddo a caldo"
+
+#: ../Thuban/UI/classgen.py:69
+msgid "Generate Classification"
+msgstr "Genera la classificazione"
+
+#: ../Thuban/UI/classgen.py:90
+msgid "Generate"
+msgstr "Genera"
+
+#: ../Thuban/UI/classgen.py:119
+#, python-format
+msgid "Field: %s"
+msgstr "Campo: %s"
+
+#: ../Thuban/UI/classgen.py:123 ../Thuban/UI/classifier.py:976
+#, python-format
+msgid "Data Type: %s"
+msgstr "Tipo di dato: %s"
+
+#: ../Thuban/UI/classgen.py:127
+msgid "Generate:"
+msgstr "Genera:"
+
+#: ../Thuban/UI/classgen.py:137
+msgid "Color Scheme:"
+msgstr "Schema colore:"
+
+#: ../Thuban/UI/classgen.py:161
+msgid "Fix Border Color"
+msgstr "Fissa il colore del bordo"
+
+#: ../Thuban/UI/classgen.py:168 ../Thuban/UI/classgen.py:936
+#: ../Thuban/UI/classgen.py:967
+msgid "Change"
+msgstr "Cambia"
+
+#: ../Thuban/UI/classgen.py:274
+msgid ""
+"Based on the data from the table and the input\n"
+"values, the exact quantiles could not be generated.\n"
+"\n"
+"Accept a close estimate?"
+msgstr ""
+"Basato sui dati della tabella e i valori\n"
+"di input, i quantili esatti non possono essere generati.\n"
+"\n"
+"Accetti una stima chiusa?"
+
+#: ../Thuban/UI/classgen.py:277
+msgid "Problem with Quantiles"
+msgstr "Problemi con i quantili"
+
+#: ../Thuban/UI/classgen.py:370
+msgid "Min:"
+msgstr "Min:"
+
+#: ../Thuban/UI/classgen.py:375
+msgid "Max:"
+msgstr "Max:"
+
+#: ../Thuban/UI/classgen.py:380 ../Thuban/UI/classgen.py:633
+msgid "Retrieve From Table"
+msgstr "Recupera dalla tabella"
+
+#: ../Thuban/UI/classgen.py:390
+msgid "Number of Groups:"
+msgstr "Numero di gruppi:"
+
+#: ../Thuban/UI/classgen.py:397
+msgid "Stepping:"
+msgstr "Passo:"
+
+#: ../Thuban/UI/classgen.py:647
+#, fuzzy
+msgid "Available"
+msgstr "- non disponibile"
+
+#: ../Thuban/UI/classgen.py:652 ../Thuban/UI/classgen.py:692
+msgid "Sort"
+msgstr "Ordina"
+
+#: ../Thuban/UI/classgen.py:655 ../Thuban/UI/classgen.py:695
+msgid "Reverse"
+msgstr "Inverti"
+
+#: ../Thuban/UI/classgen.py:687
+#, fuzzy
+msgid "Use"
+msgstr "Utente:"
+
+#: ../Thuban/UI/classgen.py:832
+msgid "Retrieve from Table"
+msgstr "Recupera dalla tabella"
+
+#: ../Thuban/UI/classgen.py:840
+msgid "Apply to Range"
+msgstr "Applica all'intervallo"
+
+#: ../Thuban/UI/classgen.py:847
+msgid "Number of Classes:"
+msgstr "Numero di classi:"
+
+#: ../Thuban/UI/classgen.py:930
+msgid "Start:"
+msgstr "Avvia:"
+
+#: ../Thuban/UI/classgen.py:961
+msgid "End:"
+msgstr "Fine:"
+
+#: ../Thuban/UI/classifier.py:164
+msgid "The Default group cannot be removed."
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:309
+#: ../Thuban/UI/classifier.py:467
+msgid "Pattern"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:306
+#: ../Thuban/UI/classifier.py:466
+msgid "Singleton"
+msgstr "Singleton"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Visible"
+msgstr "Visibile"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Symbol"
+msgstr "Simbolo"
+
+#: ../Thuban/UI/classifier.py:317 ../Thuban/UI/controls.py:33
+#: ../Thuban/UI/controls.py:177
+msgid "Value"
+msgstr "Valore"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Label"
+msgstr "Etichetta"
+
+#: ../Thuban/UI/classifier.py:462 ../Thuban/UI/classifier.py:465
+msgid "Default"
+msgstr "Predefinito"
+
+#: ../Thuban/UI/classifier.py:468
+msgid "Range"
+msgstr "Intervallo"
+
+#: ../Thuban/UI/classifier.py:469
+msgid "Map"
+msgstr "Mappa"
+
+#: ../Thuban/UI/classifier.py:759
+msgid "Text"
+msgstr "Testo"
+
+#: ../Thuban/UI/classifier.py:760
+msgid "Integer"
+msgstr "Intero"
+
+#: ../Thuban/UI/classifier.py:761
+msgid "Decimal"
+msgstr "Decimale"
+
+#: ../Thuban/UI/classifier.py:820
+msgid "Generate Class"
+msgstr "Genera classe"
+
+#: ../Thuban/UI/classifier.py:822 ../Thuban/UI/dbdialog.py:274
+msgid "Add"
+msgstr "Aggiungi"
+
+#: ../Thuban/UI/classifier.py:824
+msgid "Move Up"
+msgstr "Sposta in alto"
+
+#: ../Thuban/UI/classifier.py:826
+msgid "Move Down"
+msgstr "Sposta in basso"
+
+#: ../Thuban/UI/classifier.py:828
+msgid "Edit Symbol"
+msgstr "Modifica simbolo"
+
+#: ../Thuban/UI/classifier.py:830 ../Thuban/UI/dbdialog.py:275
+#: ../Thuban/UI/projdialog.py:117
+msgid "Remove"
+msgstr "Rimuovi"
+
+#: ../Thuban/UI/classifier.py:845
+msgid "Field: "
+msgstr "Campo:"
+
+#: ../Thuban/UI/classifier.py:1000 ../Thuban/UI/layerproperties.py:160
+msgid "Layer Properties"
+msgstr "Proprietà livello"
+
+#: ../Thuban/UI/classifier.py:1167
+msgid "Select Properties"
+msgstr "Scegli proprietà"
+
+#: ../Thuban/UI/classifier.py:1178
+msgid "Preview:"
+msgstr "Anteprima:"
+
+#: ../Thuban/UI/classifier.py:1195
+msgid "Change Line Color"
+msgstr "Cambia colore linea"
+
+#: ../Thuban/UI/classifier.py:1201 ../Thuban/UI/classifier.py:1216
+msgid "Transparent"
+msgstr "Trasparente"
+
+#: ../Thuban/UI/classifier.py:1212
+msgid "Change Fill Color"
+msgstr "Cambia colore riempimento"
+
+#: ../Thuban/UI/classifier.py:1225
+msgid "Line Width: "
+msgstr "Dimensioni linea:"
+
+#: ../Thuban/UI/classifier.py:1242
+#, fuzzy
+msgid "Size: "
+msgstr "Titolo:"
+
+#: ../Thuban/UI/classifier.py:1262 ../Thuban/UI/colordialog.py:52
+#: ../Thuban/UI/dbdialog.py:107 ../Thuban/UI/dbdialog.py:221
+#: ../Thuban/UI/labeldialog.py:41 ../Thuban/UI/layerproperties.py:81
+#: ../Thuban/UI/projdialog.py:205
+msgid "OK"
+msgstr "OK"
+
+#: ../Thuban/UI/classifier.py:1264 ../Thuban/UI/colordialog.py:53
+#: ../Thuban/UI/dbdialog.py:110 ../Thuban/UI/dbdialog.py:223
+#: ../Thuban/UI/labeldialog.py:42 ../Thuban/UI/projdialog.py:1033
+msgid "Cancel"
+msgstr "Cancella"
+
+#: ../Thuban/UI/colordialog.py:39
+#, fuzzy
+msgid "Select Color"
+msgstr "Selezione"
+
+#: ../Thuban/UI/controls.py:31
+msgid "Field"
+msgstr "Campo"
+
+#: ../Thuban/UI/dbdialog.py:41
+msgid "Choose layer from database"
+msgstr "Seleziona il livello dal database"
+
+#: ../Thuban/UI/dbdialog.py:59
+msgid "Databases"
+msgstr "Database"
+
+#: ../Thuban/UI/dbdialog.py:74
+msgid "Retrieve"
+msgstr "Recupera"
+
+#: ../Thuban/UI/dbdialog.py:82
+msgid "Tables"
+msgstr "Tabelle"
+
+#: ../Thuban/UI/dbdialog.py:92
+msgid "ID Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:98
+msgid "Geometry Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:187
+msgid "Hostname:"
+msgstr "Nome del server:"
+
+#: ../Thuban/UI/dbdialog.py:191
+msgid "Port:"
+msgstr "Porta:"
+
+#: ../Thuban/UI/dbdialog.py:198
+msgid "Database Name:"
+msgstr "Nome del database:"
+
+#: ../Thuban/UI/dbdialog.py:206
+msgid "User:"
+msgstr "Utente:"
+
+#: ../Thuban/UI/dbdialog.py:211
+msgid "Password:"
+msgstr "Password:"
+
+#: ../Thuban/UI/dbdialog.py:286
+msgid "Database Management"
+msgstr "Gestione del database"
+
+#: ../Thuban/UI/dbdialog.py:361 ../Thuban/UI/dbdialog.py:366
+msgid "Add Database"
+msgstr "Aggiungi database"
+
+#: ../Thuban/UI/dbdialog.py:367
+#, python-format
+msgid "Connection '%s' already exists"
+msgstr "La connessione '%s' è già in uso"
+
+#: ../Thuban/UI/dbdialog.py:388
+msgid "Remove Database Connection"
+msgstr "Elimina la connessione al database"
+
+#: ../Thuban/UI/dbdialog.py:389
+#, python-format
+msgid ""
+"The connection %s\n"
+"is still in use"
+msgstr ""
+"La connessione %s\n"
+"è attualmente in uso"
+
+#: ../Thuban/UI/dock.py:190
+msgid "Undock"
+msgstr "Elimina dal pannello"
+
+#: ../Thuban/UI/dock.py:218
+msgid "Dock"
+msgstr "Aggiungi al pannello"
+
+#: ../Thuban/UI/exceptiondialog.py:23 ../Thuban/UI/exceptiondialog.py:61
+msgid "Thuban: Internal Error"
+msgstr "Thuban: errore interno"
+
+#: ../Thuban/UI/exceptiondialog.py:43
+msgid "Proceed"
+msgstr "Continua"
+
+#: ../Thuban/UI/exceptiondialog.py:44
+msgid "Exit Thuban now"
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:72
+msgid "Initialization not yet requested."
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:88
+msgid "Initialization successful."
+msgstr ""
+
+#: ../Thuban/UI/identifyview.py:44
+msgid "Identify Shape"
+msgstr "Identifica geometria"
+
+#: ../Thuban/UI/identifyview.py:56
+msgid "Close Window"
+msgstr "Chiudi finestra"
+
+#: ../Thuban/UI/identifyview.py:57
+msgid "Stop Identify Mode"
+msgstr "Fine identificazione elemento"
+
+#: ../Thuban/UI/join.py:64
+msgid "Join"
+msgstr "Unisci"
+
+#: ../Thuban/UI/join.py:71 ../Thuban/UI/join.py:72
+#, fuzzy
+msgid "Select..."
+msgstr "Selezione"
+
+#: ../Thuban/UI/join.py:100 ../Thuban/UI/join.py:108
+msgid "Table:"
+msgstr "Tabella:"
+
+#: ../Thuban/UI/join.py:111 ../Thuban/UI/join.py:114
+msgid "Field:"
+msgstr "Campo:"
+
+#: ../Thuban/UI/join.py:125
+msgid "Outer Join (preserves left table records)"
+msgstr "Unione esterna (conserva i valori della tabella di sinistra)"
+
+#: ../Thuban/UI/join.py:173
+#, python-format
+msgid ""
+"Join failed:\n"
+"  %s"
+msgstr ""
+"Unione fallita:\n"
+"  %s"
+
+#: ../Thuban/UI/join.py:174
+msgid "Info"
+msgstr "Informazioni"
+
+#: ../Thuban/UI/join.py:195
+#, fuzzy, python-format
+msgid ""
+"The joined table has %(joined)d rows but it must have %(needed)d rows to be "
+"used with the selected layer"
+msgstr ""
+"La tabella ha unito % righe ma ha bisogno di altre % righe per essere usato "
+"con il livello selezionato"
+
+#: ../Thuban/UI/join.py:200
+msgid "Join Failed"
+msgstr "Unione fallita"
+
+#: ../Thuban/UI/join.py:209 ../Thuban/UI/mainwindow.py:915
+#, python-format
+msgid "Table: %s"
+msgstr "Tabella: %s"
+
+#: ../Thuban/UI/labeldialog.py:26
+msgid "Label Values"
+msgstr "Valori per le etichette"
+
+#: ../Thuban/UI/layerproperties.py:54
+msgid "Title: "
+msgstr "Titolo:"
+
+#: ../Thuban/UI/layerproperties.py:65
+#, fuzzy, python-format
+msgid "Layer Type: %s"
+msgstr "Tabella del livello: %s"
+
+#: ../Thuban/UI/layerproperties.py:71
+#, fuzzy
+msgid "Projection: None"
+msgstr "Proiezione:"
+
+#: ../Thuban/UI/layerproperties.py:73
+#, fuzzy, python-format
+msgid "Projection: %s"
+msgstr "Proiezione:"
+
+#: ../Thuban/UI/layerproperties.py:79 ../Thuban/UI/projdialog.py:199
+msgid "Try"
+msgstr "Prova"
+
+#: ../Thuban/UI/layerproperties.py:80 ../Thuban/UI/projdialog.py:202
+msgid "Revert"
+msgstr "Annulla"
+
+#: ../Thuban/UI/legend.py:75
+msgid "Top Layer"
+msgstr "Sposta in cima"
+
+#: ../Thuban/UI/legend.py:79
+msgid "Raise Layer"
+msgstr "Sposta sopra"
+
+#: ../Thuban/UI/legend.py:83
+msgid "Lower Layer"
+msgstr "Sposta sotto"
+
+#: ../Thuban/UI/legend.py:87
+msgid "Bottom Layer"
+msgstr "Sposta in fondo"
+
+#: ../Thuban/UI/legend.py:91
+msgid "Show Layer"
+msgstr "Mostra livello"
+
+#: ../Thuban/UI/legend.py:95
+msgid "Hide Layer"
+msgstr "Nascondi livello"
+
+#: ../Thuban/UI/legend.py:99
+msgid "Edit Layer Properties"
+msgstr "Modifica proprietà del livello"
+
+#: ../Thuban/UI/mainwindow.py:264 ../Thuban/UI/mainwindow.py:286
+#, python-format
+msgid "Unknown command %s"
+msgstr "Comando sconosciuto %s"
+
+#: ../Thuban/UI/mainwindow.py:299
+#, python-format
+msgid "Unknown command ID %d"
+msgstr "ID comando sconosciuto %d"
+
+#: ../Thuban/UI/mainwindow.py:338
+#, python-format
+msgid "The Dialog named %s is already open"
+msgstr "Esiste già una finestra di dialogo con nome %s"
+
+#: ../Thuban/UI/mainwindow.py:396
+#, python-format
+msgid "Select layer '%s' and pick a projection using Layer/Projection..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:449
+msgid "Exit"
+msgstr "Esci"
+
+#: ../Thuban/UI/mainwindow.py:450
+msgid "The session has been modified. Do you want to save it?"
+msgstr "La sessione è stata modificata. Vuoi salvarla?"
+
+#: ../Thuban/UI/mainwindow.py:465
+msgid "Open Session"
+msgstr "Apri sessione"
+
+#: ../Thuban/UI/mainwindow.py:487
+msgid "Save Session As"
+msgstr "Salva sessione con nome"
+
+#: ../Thuban/UI/mainwindow.py:561
+msgid "Select one or more data files"
+msgstr "Selezione uno o più file di dati"
+
+#: ../Thuban/UI/mainwindow.py:576
+msgid "Add Layer"
+msgstr "Aggiungi un livello"
+
+#: ../Thuban/UI/mainwindow.py:577 ../Thuban/UI/mainwindow.py:602
+#: ../Thuban/UI/mainwindow.py:862
+#, python-format
+msgid "Can't open the file '%s'."
+msgstr "Impossibile aprire il file '%s'"
+
+#: ../Thuban/UI/mainwindow.py:589
+msgid "Select an image file"
+msgstr "Scegli un file immagine"
+
+#: ../Thuban/UI/mainwindow.py:601
+msgid "Add Image Layer"
+msgstr "Aggiungi un livello immagine"
+
+#: ../Thuban/UI/mainwindow.py:629
+msgid "Add Layer from database"
+msgstr "Aggiungi un livello dal database"
+
+#: ../Thuban/UI/mainwindow.py:630
+#, python-format
+msgid "Can't open the database table '%s'"
+msgstr "Impossibile aprire la tabella '%s' dal database"
+
+#: ../Thuban/UI/mainwindow.py:719
+#, python-format
+msgid "Copy of `%s'"
+msgstr "Copia di '%s'"
+
+#: ../Thuban/UI/mainwindow.py:749
+#, python-format
+msgid "Layer Table: %s"
+msgstr "Tabella del livello: %s"
+
+#: ../Thuban/UI/mainwindow.py:764
+#, python-format
+msgid "Map Projection: %s"
+msgstr "Proiezione mappa: %s"
+
+#: ../Thuban/UI/mainwindow.py:779
+#, python-format
+msgid "Layer Projection: %s"
+msgstr "Proiezione livello: %s"
+
+#: ../Thuban/UI/mainwindow.py:812
+msgid "Join Layer with Table"
+msgstr "Unisci il livello con la tabella"
+
+#: ../Thuban/UI/mainwindow.py:834 ../Thuban/UI/mainwindow.py:1165
+msgid "Legend"
+msgstr "Legenda"
+
+#: ../Thuban/UI/mainwindow.py:848 ../Thuban/UI/mainwindow.py:861
+msgid "Open Table"
+msgstr "Apri tabella"
+
+#: ../Thuban/UI/mainwindow.py:850
+msgid "DBF Files (*.dbf)"
+msgstr "File DBF (*.dbf)"
+
+#: ../Thuban/UI/mainwindow.py:873
+msgid "Pick the tables to close:"
+msgstr "Seleziona le tabelle da chiudere:"
+
+#: ../Thuban/UI/mainwindow.py:874
+msgid "Close Table"
+msgstr "Chiudi tabella"
+
+#: ../Thuban/UI/mainwindow.py:894
+msgid "Pick the table to show:"
+msgstr "Seleziona la tabella da mostrare"
+
+#: ../Thuban/UI/mainwindow.py:895
+msgid "Show Table"
+msgstr "Mostra tabella"
+
+#: ../Thuban/UI/mainwindow.py:906
+msgid "Join Tables"
+msgstr "Unisci tabelle"
+
+#: ../Thuban/UI/mainwindow.py:929
+msgid "Pick the table to rename:"
+msgstr "Seleziona la tabella da rinominare:"
+
+#: ../Thuban/UI/mainwindow.py:930 ../Thuban/UI/mainwindow.py:942
+msgid "Rename Table"
+msgstr "Rinomina tabella"
+
+#: ../Thuban/UI/mainwindow.py:942
+#, fuzzy
+msgid "Table Title:"
+msgstr "Tabella:"
+
+#: ../Thuban/UI/mainwindow.py:991
+#, fuzzy
+msgid "Map Title:"
+msgstr "Titolo:"
+
+#: ../Thuban/UI/mainwindow.py:991
+#, fuzzy
+msgid "Rename Map"
+msgstr "Rinomina la mappa"
+
+#: ../Thuban/UI/mainwindow.py:1004
+#, fuzzy
+msgid "Layer Title:"
+msgstr "Tabella del livello: %s"
+
+#: ../Thuban/UI/mainwindow.py:1004
+#, fuzzy
+msgid "Rename Layer"
+msgstr "&Rimuovi livello"
+
+#: ../Thuban/UI/mainwindow.py:1057
+#, python-format
+msgid "Thuban - %s"
+msgstr "Thuban - %s"
+
+#: ../Thuban/UI/mainwindow.py:1059
+msgid "Thuban"
+msgstr "Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1154
+msgid "&New Session"
+msgstr "&Nuova sessione"
+
+#: ../Thuban/UI/mainwindow.py:1155
+msgid "Start a new session"
+msgstr "Comincia una nuova sessione"
+
+#: ../Thuban/UI/mainwindow.py:1156
+msgid "&Open Session..."
+msgstr "Apri sessi&one"
+
+#: ../Thuban/UI/mainwindow.py:1157
+msgid "Open a session file"
+msgstr "Apri un file sessione"
+
+#: ../Thuban/UI/mainwindow.py:1158
+msgid "&Save Session"
+msgstr "&Salva sessione"
+
+#: ../Thuban/UI/mainwindow.py:1159
+msgid "Save this session to the file it was opened from"
+msgstr "Salva questa sessione nel file d'origine"
+
+#: ../Thuban/UI/mainwindow.py:1160
+msgid "Save Session &As..."
+msgstr "Salv&a sessione come..."
+
+#: ../Thuban/UI/mainwindow.py:1161
+msgid "Save this session to a new file"
+msgstr "Sava la sessione corrente in un nuovo file"
+
+#: ../Thuban/UI/mainwindow.py:1162
+msgid "Session &Tree"
+msgstr "Al&bero della sessione"
+
+#: ../Thuban/UI/mainwindow.py:1164
+msgid "Toggle on/off the session tree analysis window"
+msgstr "Mostra/Nascondi la finestra con l'analisi dell'albero della sessione"
+
+#: ../Thuban/UI/mainwindow.py:1167
+msgid "Toggle Legend on/off"
+msgstr "Mostra/Nascondi legenda"
+
+#: ../Thuban/UI/mainwindow.py:1168
+msgid "&Database Connections..."
+msgstr "Connetti &database..."
+
+#: ../Thuban/UI/mainwindow.py:1171
+msgid "E&xit"
+msgstr "E&sci"
+
+#: ../Thuban/UI/mainwindow.py:1172
+msgid "Finish working with Thuban"
+msgstr "Concludi il lavoro con Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1175
+msgid "&About..."
+msgstr "Inform&azioni..."
+
+#: ../Thuban/UI/mainwindow.py:1176
+msgid "Info about Thuban authors, version and modules"
+msgstr "Informazioni sugli autori di Thuban, versione e moduli"
+
+#: ../Thuban/UI/mainwindow.py:1180 ../Thuban/UI/mainwindow.py:1228
+msgid "Pro&jection..."
+msgstr "Pro&iezione..."
+
+#: ../Thuban/UI/mainwindow.py:1181
+msgid "Set or change the map projection"
+msgstr "Definisci o cambia la proiezione della mappa"
+
+#: ../Thuban/UI/mainwindow.py:1183
+msgid "&Zoom in"
+msgstr "&Zoom in"
+
+#: ../Thuban/UI/mainwindow.py:1184
+msgid "Switch to map-mode 'zoom-in'"
+msgstr "Zoom in della mappa"
+
+#: ../Thuban/UI/mainwindow.py:1186
+msgid "Zoom &out"
+msgstr "Zoom &out"
+
+#: ../Thuban/UI/mainwindow.py:1187
+msgid "Switch to map-mode 'zoom-out'"
+msgstr "Zoom out della mappa"
+
+#: ../Thuban/UI/mainwindow.py:1189
+msgid "&Pan"
+msgstr "S&posta"
+
+#: ../Thuban/UI/mainwindow.py:1190
+msgid "Switch to map-mode 'pan'"
+msgstr "Sposta la mappa"
+
+#: ../Thuban/UI/mainwindow.py:1192
+msgid "&Identify"
+msgstr "&Identifica"
+
+#: ../Thuban/UI/mainwindow.py:1194
+msgid "Switch to map-mode 'identify'"
+msgstr "Identifica elemento"
+
+#: ../Thuban/UI/mainwindow.py:1196
+msgid "&Label"
+msgstr "&Etichetta"
+
+#: ../Thuban/UI/mainwindow.py:1197
+msgid "Add/Remove labels"
+msgstr "Aggiungi/Rimuovi etichette"
+
+#: ../Thuban/UI/mainwindow.py:1199
+msgid "&Full extent"
+msgstr "Estensione &massima"
+
+#: ../Thuban/UI/mainwindow.py:1200
+msgid "Zoom to the full map extent"
+msgstr "Zoom all'estensione massima della mappa"
+
+#: ../Thuban/UI/mainwindow.py:1202
+msgid "&Full layer extent"
+msgstr "Estensione massima &livello"
+
+#: ../Thuban/UI/mainwindow.py:1203
+msgid "Zoom to the full layer extent"
+msgstr "Zoom all'estensione massima del livello"
+
+#: ../Thuban/UI/mainwindow.py:1205
+msgid "&Full selection extent"
+msgstr "Estensione all'elemento &selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1207
+msgid "Zoom to the full selection extent"
+msgstr "Zoom all'estensione del elemento selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1209
+msgid "E&xport"
+msgstr "Es&porta"
+
+#: ../Thuban/UI/mainwindow.py:1210
+msgid "Export the map to file"
+msgstr "Esporta la mappa in un file"
+
+#: ../Thuban/UI/mainwindow.py:1211
+msgid "Prin&t"
+msgstr "Stam&pa"
+
+#: ../Thuban/UI/mainwindow.py:1212
+msgid "Print the map"
+msgstr "Stampa la mappa"
+
+#: ../Thuban/UI/mainwindow.py:1213 ../Thuban/UI/mainwindow.py:1299
+msgid "&Rename..."
+msgstr "Ri&nomina..."
+
+#: ../Thuban/UI/mainwindow.py:1214
+msgid "Rename the map"
+msgstr "Rinomina la mappa"
+
+#: ../Thuban/UI/mainwindow.py:1215
+msgid "&Add Layer..."
+msgstr "Aggiungi un &vettoriale"
+
+#: ../Thuban/UI/mainwindow.py:1216
+msgid "Add a new layer to the map"
+msgstr "Aggiungi un nuovo livello alla mappa"
+
+#: ../Thuban/UI/mainwindow.py:1217
+msgid "&Add Image Layer..."
+msgstr "Aggiungi un livello &immagine"
+
+#: ../Thuban/UI/mainwindow.py:1218
+msgid "Add a new image layer to the map"
+msgstr "Aggiunge un nuovo livello immagine alla mappa"
+
+#: ../Thuban/UI/mainwindow.py:1220
+msgid "Add &Database Layer..."
+msgstr "Aggiungi un livello dal &database..."
+
+#: ../Thuban/UI/mainwindow.py:1221
+msgid "Add a new database layer to active map"
+msgstr "Aggiungi un nuovo livello dal database alla mappa in uso"
+
+#: ../Thuban/UI/mainwindow.py:1223
+msgid "&Remove Layer"
+msgstr "&Rimuovi livello"
+
+#: ../Thuban/UI/mainwindow.py:1224
+msgid "Remove selected layer"
+msgstr "Rimuove il livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1230
+msgid "Specify projection for selected layer"
+msgstr "Specifica la proiezione del livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1231
+msgid "&Duplicate"
+msgstr "&Duplica"
+
+#: ../Thuban/UI/mainwindow.py:1232
+msgid "Duplicate selected layer"
+msgstr "Crea una copia del livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1234
+msgid "Re&name ..."
+msgstr "Ri&nomina"
+
+#: ../Thuban/UI/mainwindow.py:1235
+msgid "Rename selected layer"
+msgstr "Rinomina il livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1237
+msgid "&Raise"
+msgstr "Al&za"
+
+#: ../Thuban/UI/mainwindow.py:1238
+msgid "Raise selected layer"
+msgstr "Alza il livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1240
+msgid "&Lower"
+msgstr "A&bbassa"
+
+#: ../Thuban/UI/mainwindow.py:1241
+msgid "Lower selected layer"
+msgstr "Abbassa il livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1243
+msgid "&Show"
+msgstr "&Mostra"
+
+#: ../Thuban/UI/mainwindow.py:1244
+msgid "Make selected layer visible"
+msgstr "Rendi i livello selezionato visibile"
+
+#: ../Thuban/UI/mainwindow.py:1246
+msgid "&Hide"
+msgstr "&Nascondi"
+
+#: ../Thuban/UI/mainwindow.py:1247
+msgid "Make selected layer unvisible"
+msgstr "Rendi il livello invisibile"
+
+#: ../Thuban/UI/mainwindow.py:1249
+msgid "Show Ta&ble"
+msgstr "Mostra ta&bella"
+
+#: ../Thuban/UI/mainwindow.py:1250
+msgid "Show the selected layer's table"
+msgstr "Mostra la tabella del livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1252
+msgid "&Properties..."
+msgstr "&Proprietà..."
+
+#: ../Thuban/UI/mainwindow.py:1254
+msgid "Edit the properties of the selected layer"
+msgstr "Modifica proprietà del livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1255
+msgid "&Join Table..."
+msgstr "&Unisci tabella..."
+
+#: ../Thuban/UI/mainwindow.py:1257
+msgid "Join and attach a table to the selected layer"
+msgstr "Unisci e collega una tabella al livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1260
+msgid "&Top"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1261
+#, fuzzy
+msgid "Put selected layer to the top"
+msgstr "Crea una copia del livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1263
+#, fuzzy
+msgid "&Bottom"
+msgstr "Sposta in fondo"
+
+#: ../Thuban/UI/mainwindow.py:1264
+#, fuzzy
+msgid "Put selected layer to the bottom"
+msgstr "Crea una copia del livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1266
+#, fuzzy
+msgid "&Visible"
+msgstr "Visibile"
+
+#: ../Thuban/UI/mainwindow.py:1268
+#, fuzzy
+msgid "Toggle visibility of selected layer"
+msgstr "Alza il livello selezionato"
+
+#: ../Thuban/UI/mainwindow.py:1285
+msgid "&Unjoin Table..."
+msgstr "&Separa tabella..."
+
+#: ../Thuban/UI/mainwindow.py:1287
+msgid "Undo the last join operation"
+msgstr "Annulla l'ultima operazione di unione "
+
+#: ../Thuban/UI/mainwindow.py:1294
+msgid "&Open..."
+msgstr "&Apri..."
+
+#: ../Thuban/UI/mainwindow.py:1295
+msgid "Open a DBF-table from a file"
+msgstr "Apri una tabella DBF da file"
+
+#: ../Thuban/UI/mainwindow.py:1296
+msgid "&Close..."
+msgstr "&Chiudi..."
+
+#: ../Thuban/UI/mainwindow.py:1298
+msgid "Close one or more tables from a list"
+msgstr "Chiudi una o più tabelle dalla lista"
+
+#: ../Thuban/UI/mainwindow.py:1301
+msgid "Rename one or more tables"
+msgstr "Rinomina una o più tabelle dalla lista"
+
+#: ../Thuban/UI/mainwindow.py:1302
+msgid "&Show..."
+msgstr "&Mostra..."
+
+#: ../Thuban/UI/mainwindow.py:1304
+msgid "Show one or more tables in a dialog"
+msgstr "Mostra una o più tabelle in una finestra"
+
+#: ../Thuban/UI/mainwindow.py:1305
+msgid "&Join..."
+msgstr "&Unisci..."
+
+#: ../Thuban/UI/mainwindow.py:1307
+msgid "Join two tables creating a new one"
+msgstr "Unisci due tabelle creandone una nuova"
+
+#: ../Thuban/UI/mainwindow.py:1331
+msgid "&File"
+msgstr "&File"
+
+#: ../Thuban/UI/mainwindow.py:1337
+msgid "&Map"
+msgstr "&Mappa"
+
+#: ../Thuban/UI/mainwindow.py:1338
+msgid "&Layer"
+msgstr "&Livello"
+
+#: ../Thuban/UI/mainwindow.py:1352
+msgid "&Table"
+msgstr "&Tabella"
+
+#: ../Thuban/UI/mainwindow.py:1358
+msgid "&Help"
+msgstr "&Aiuto"
+
+#: ../Thuban/UI/menu.py:90
+#, python-format
+msgid "Submenu %s doesn't exist"
+msgstr "Il sottomenu %s non esiste"
+
+#: ../Thuban/UI/projdialog.py:62 ../Thuban/UI/projdialog.py:776
+msgid "Transverse Mercator"
+msgstr "Mercatore Transversa"
+
+#: ../Thuban/UI/projdialog.py:63 ../Thuban/UI/projdialog.py:842
+msgid "Universal Transverse Mercator"
+msgstr "Mercatore Transversa Universale"
+
+#: ../Thuban/UI/projdialog.py:64 ../Thuban/UI/projdialog.py:918
+msgid "Lambert Conic Conformal"
+msgstr "Lambert conica conforme"
+
+#: ../Thuban/UI/projdialog.py:65 ../Thuban/UI/projdialog.py:66
+#: ../Thuban/UI/projdialog.py:968
+msgid "Geographic"
+msgstr "Geografica"
+
+#: ../Thuban/UI/projdialog.py:110
+msgid "Import..."
+msgstr "Importa..."
+
+#: ../Thuban/UI/projdialog.py:113
+msgid "Export..."
+msgstr "Esporta..."
+
+#: ../Thuban/UI/projdialog.py:122
+msgid "Show EPSG:"
+msgstr "Mostra EPSG:"
+
+#: ../Thuban/UI/projdialog.py:124
+msgid "Normal"
+msgstr "Normale"
+
+#: ../Thuban/UI/projdialog.py:127
+msgid "Deprecated"
+msgstr "Deprecato"
+
+#: ../Thuban/UI/projdialog.py:138
+msgid "Edit"
+msgstr "Modifica"
+
+#: ../Thuban/UI/projdialog.py:148
+msgid "Name:"
+msgstr "Nome:"
+
+#: ../Thuban/UI/projdialog.py:156
+msgid "Projection:"
+msgstr "Proiezione:"
+
+#: ../Thuban/UI/projdialog.py:167 ../Thuban/UI/projdialog.py:648
+msgid "<Unknown>"
+msgstr "<Sconosciuto>"
+
+#: ../Thuban/UI/projdialog.py:183
+msgid "New"
+msgstr "Nuovo"
+
+#: ../Thuban/UI/projdialog.py:186
+msgid "Add to List"
+msgstr "Aggiungi alla lista"
+
+#: ../Thuban/UI/projdialog.py:190
+msgid "Update"
+msgstr "Aggiorna"
+
+#: ../Thuban/UI/projdialog.py:295
+#, python-format
+msgid ""
+"Warnings when reading \"%s\":\n"
+"\n"
+"%s"
+msgstr ""
+"Avvertimenti durante la lettura di \"%s\":\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/projdialog.py:306
+msgid "Import"
+msgstr "Importa"
+
+#: ../Thuban/UI/projdialog.py:319 ../Thuban/UI/projdialog.py:617
+msgid "Warnings"
+msgstr "Avvertimenti"
+
+#: ../Thuban/UI/projdialog.py:337 ../Thuban/UI/tableview.py:386
+msgid "Export"
+msgstr "Esporta"
+
+#: ../Thuban/UI/projdialog.py:389
+msgid "The following error occured:\n"
+msgstr "Si è verificato il seguente errore:\n"
+
+#: ../Thuban/UI/projdialog.py:391
+msgid "Error"
+msgstr "Errore"
+
+#: ../Thuban/UI/projdialog.py:460
+msgid "No Projections selected"
+msgstr "Non sono state selezionate proiezioni"
+
+#: ../Thuban/UI/projdialog.py:470
+#, python-format
+msgid "Source of Projection: %s"
+msgstr "Sorgente della proiezione: %s"
+
+#: ../Thuban/UI/projdialog.py:502
+msgid "Multiple Projections selected"
+msgstr "Proiezioni multiple selezionate"
+
+#: ../Thuban/UI/projdialog.py:649
+msgid "Airy"
+msgstr "Airy"
+
+#: ../Thuban/UI/projdialog.py:650
+msgid "Bessel 1841"
+msgstr "Bessel 1841"
+
+#: ../Thuban/UI/projdialog.py:651
+msgid "Clarke 1866"
+msgstr "Clarke 1866"
+
+#: ../Thuban/UI/projdialog.py:652
+msgid "Clarke 1880"
+msgstr "Clarke 1880"
+
+#: ../Thuban/UI/projdialog.py:653
+msgid "GRS 1980 (IUGG, 1980)"
+msgstr "GRS 1980 (IUGG, 1980)"
+
+#: ../Thuban/UI/projdialog.py:654
+msgid "International 1909 (Hayford)"
+msgstr "International 1909 (Hayford)"
+
+#: ../Thuban/UI/projdialog.py:655
+msgid "WGS 84"
+msgstr "WGS 84"
+
+#: ../Thuban/UI/projdialog.py:667
+msgid "Ellipsoid:"
+msgstr "Ellissoide:"
+
+#: ../Thuban/UI/projdialog.py:716
+msgid ""
+"Thuban does not know the parameters\n"
+"for the current projection and cannot\n"
+"display a configuration panel.\n"
+"\n"
+"The unidentified set of parameters is:\n"
+"\n"
+msgstr ""
+"Thuban non è in grado di riconoscere i parametri\n"
+"dell'attuale proizione e quindi non puòn mostrare un pannello di "
+"configurazione\n"
+"\n"
+"L'insieme non identificato di parametri è:\n"
+"\n"
+
+#: ../Thuban/UI/projdialog.py:762
+msgid "Latitude:"
+msgstr "Latitudine:"
+
+#: ../Thuban/UI/projdialog.py:764
+msgid "Longitude:"
+msgstr "Longitudine:"
+
+#: ../Thuban/UI/projdialog.py:766 ../Thuban/UI/projdialog.py:910
+msgid "False Easting:"
+msgstr "Falso est:"
+
+#: ../Thuban/UI/projdialog.py:768 ../Thuban/UI/projdialog.py:912
+msgid "False Northing:"
+msgstr "Falso nord:"
+
+#: ../Thuban/UI/projdialog.py:770
+msgid "Scale Factor:"
+msgstr "Fattore di scala:"
+
+#: ../Thuban/UI/projdialog.py:821
+msgid "Propose"
+msgstr "Proponi"
+
+#: ../Thuban/UI/projdialog.py:823
+msgid "Southern Hemisphere"
+msgstr "Emisfero meridionale"
+
+#: ../Thuban/UI/projdialog.py:833
+msgid "Zone:"
+msgstr "Zona:"
+
+#: ../Thuban/UI/projdialog.py:870
+msgid "Can not propose: No bounding box found."
+msgstr ""
+"non riesco a proporre: non è possibile trovare un rettangolo di confine"
+
+#: ../Thuban/UI/projdialog.py:871 ../Thuban/UI/projdialog.py:1008
+msgid "Projection: Propose UTM Zone"
+msgstr "Proiezione: proponi zona UTM"
+
+#: ../Thuban/UI/projdialog.py:901
+msgid "Latitude of first standard parallel:"
+msgstr "Latitudine del primo parallelo standard:"
+
+#: ../Thuban/UI/projdialog.py:904
+msgid "Latitude of second standard parallel:"
+msgstr "Latitutidine del secondo parallelo standard:"
+
+#: ../Thuban/UI/projdialog.py:906
+msgid "Central Meridian:"
+msgstr "Meridiano centrale:"
+
+#: ../Thuban/UI/projdialog.py:908
+msgid "Latitude of origin:"
+msgstr "Latitudine di origine:"
+
+#: ../Thuban/UI/projdialog.py:958
+msgid "Degrees"
+msgstr "Gradi"
+
+#: ../Thuban/UI/projdialog.py:959
+msgid "Radians"
+msgstr "Radianti"
+
+#: ../Thuban/UI/projdialog.py:992
+msgid "Source Data is in: "
+msgstr "La sorgente dati è in: "
+
+#: ../Thuban/UI/projdialog.py:1021
+msgid "The current map extent center lies in UTM Zone"
+msgstr "L'attuale centro dell'estensione corrente della mappa è nella zona UTM"
+
+#: ../Thuban/UI/projdialog.py:1031
+msgid "Take"
+msgstr "Prendi"
+
+#: ../Thuban/UI/projlist.py:51
+msgid "Available Projections"
+msgstr "Proiezioni disponibili"
+
+#: ../Thuban/UI/projlist.py:112
+msgid "<None>"
+msgstr "<Nulla>"
+
+#: ../Thuban/UI/projlist.py:117
+#, python-format
+msgid "%s (current)"
+msgstr "%s (attuale)"
+
+#: ../Thuban/UI/rasterlayerproperties.py:41
+msgid "GDAL image information unavailable. See About box for details."
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:49
+#, fuzzy
+msgid "Extent (lat-lon): None"
+msgstr "Estensione (lat-lon):"
+
+#: ../Thuban/UI/rasterlayerproperties.py:56
+#, fuzzy
+msgid "Image Properties"
+msgstr "Proprietà livello"
+
+#: ../Thuban/UI/rasterlayerproperties.py:61
+#, python-format
+msgid "Source: %s"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:71
+#, fuzzy, python-format
+msgid "Driver: %s"
+msgstr "Campo: %s"
+
+#: ../Thuban/UI/rasterlayerproperties.py:74
+#, python-format
+msgid "Size: %ix%i"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:77
+#, fuzzy, python-format
+msgid "Number of Bands: %i"
+msgstr "Numero di classi:"
+
+#: ../Thuban/UI/rasterlayerproperties.py:93
+msgid "Mask Type"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:99
+msgid "Opacity:"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:381
+msgid "Replace Selection"
+msgstr "Sostituisci la selezione"
+
+#: ../Thuban/UI/tableview.py:382
+msgid "Refine Selection"
+msgstr "Redefinisci selezione"
+
+#: ../Thuban/UI/tableview.py:383
+msgid "Add to Selection"
+msgstr "Aggiungi alla selezione"
+
+#: ../Thuban/UI/tableview.py:385
+msgid "Query"
+msgstr "Interroga"
+
+#: ../Thuban/UI/tableview.py:387
+msgid "Export Selection"
+msgstr "Esporta selezione"
+
+#: ../Thuban/UI/tableview.py:413
+msgid "Selection"
+msgstr "Selezione"
+
+#: ../Thuban/UI/tableview.py:455
+#, python-format
+msgid "%i rows (%i selected), %i columns"
+msgstr "%i righe (%i selezionate), %i colonne"
+
+#: ../Thuban/UI/tableview.py:535
+msgid "Export Table To"
+msgstr "Esporta la tabella in"
+
+#: ../Thuban/UI/tableview.py:536
+msgid "DBF Files (*.dbf)|*.dbf|"
+msgstr "File DBF (*.dbf)|*.dbf|"
+
+#: ../Thuban/UI/tableview.py:537
+msgid "CSV Files (*.csv)|*.csv|"
+msgstr "File CSV (*.csv)|*.csv|"
+
+#: ../Thuban/UI/tableview.py:538
+msgid "All Files (*.*)|*.*"
+msgstr "Tutti i file (*.*)|*.*"
+
+#: ../Thuban/UI/tree.py:226
+msgid "Session"
+msgstr "Sessione"
+
+#: ../Thuban/UI/view.py:285
+msgid "Export Map"
+msgstr "Esporta mappa"
+
+#~ msgid "Type: %s"
+#~ msgstr "Tipo: %s"
+
+#~ msgid "Projection: UTM Parameters"
+#~ msgstr "Proiezione: parametri UTM"
+
+#~ msgid "UTM Zone"
+#~ msgstr "Zona UTM"
+
+#~ msgid "Ellipsoid"
+#~ msgstr "Ellissoide"
+
+#~ msgid "Based on the data from the table and the input\n"
+#~ msgstr "Basato dai dati recuperati dalla tabella e dall'input\n"
+
+#~ msgid "Select a data file"
+#~ msgstr "Scegli un file di dati"
+
+#~ msgid "Thuban does not know the parameters for the "
+#~ msgstr "Thuban non conosce i parametri per "
+
+#~ msgid "Unhandled shape type %s"
+#~ msgstr "Tipo di geometria non supporta %s"

Added: packages/thuban/branches/upstream/current/po/pt_BR.po
===================================================================
--- packages/thuban/branches/upstream/current/po/pt_BR.po	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/po/pt_BR.po	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1849 @@
+# Thuban Translation File for Brazilian Portuguese
+# Arquivo de Tradução do Thuban para o Português Brasileiro
+# Copyright (C) 2004
+# This file is distributed under the same license as the Thuban package.
+# Eduardo Patto Kanegae <eduardo at consultoria.eti.br>, 2004.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Thuban 1.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-03-13 20:15+0000\n"
+"PO-Revision-Date: 2004-01-15 16:07+0300\n"
+"Last-Translator: Eduardo Patto Kanegae <eduardo at consultoria.eti.br>\n"
+"Language-Team: Thuban <thuban at intevation.de>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../Thuban/version.py:189
+#, python-format
+msgid "%s %s < %s"
+msgstr "%s %s < %s"
+
+#: ../Thuban/version.py:195
+#, python-format
+msgid "Thuban was compiled with wx %(wxproj-wx)s but wxPython is %(wxPython)s"
+msgstr ""
+
+#: ../Thuban/Lib/connector.py:65
+#, python-format
+msgid "no receivers for channel %s of %s"
+msgstr "nenhum receptor para o canal %s de %s"
+
+#: ../Thuban/Lib/connector.py:70
+#, python-format
+msgid "receiver %s%s is not connected to channel %s of %s"
+msgstr "receptor %s%s não está conectado ao canal %s de %s"
+
+#: ../Thuban/Lib/connector.py:94
+#, python-format
+msgid "Warning: %s.%s: %s%s\n"
+msgstr "Aviso: %s.%s: %s%s\n"
+
+#: ../Thuban/Lib/connector.py:118
+#, python-format
+msgid "\tmethod %s of %s"
+msgstr "\tmétodo %s de %s"
+
+#: ../Thuban/Lib/fileutil.py:87 ../Thuban/Lib/fileutil.py:141
+msgid "first argument must be an absolute filename"
+msgstr "primeiro argumento deve ser um nome absoluto de arquivo"
+
+#: ../Thuban/Lib/fileutil.py:138
+msgid "Both parameters must have a drive letter"
+msgstr "Ambos os parâmetros devem ter uma letra de drive"
+
+#: ../Thuban/Lib/fileutil.py:198
+msgid "No implementation of get_application_dir available for platform"
+msgstr ""
+"Nenhuma implementação de get_application_dir disponível para a plataforma"
+
+#: ../Thuban/Lib/fileutil.py:208
+msgid "No implementation of relative_filename available for platform"
+msgstr ""
+"Nenhuma implementação de relative_filename disponível para a plataforma"
+
+#: ../Thuban/Model/classgen.py:338
+msgid "invalid index"
+msgstr "índice inválido"
+
+#: ../Thuban/Model/classification.py:309 ../Thuban/UI/classifier.py:758
+msgid "None"
+msgstr "Nenhum"
+
+#: ../Thuban/Model/classification.py:325
+msgid "Line Color"
+msgstr "Cor da Linha"
+
+#: ../Thuban/Model/classification.py:327
+#, python-format
+msgid "Line Width: %s"
+msgstr "Espessura da Linha: %s"
+
+#: ../Thuban/Model/classification.py:333
+#, fuzzy, python-format
+msgid "Size: %s"
+msgstr "Campo: %s"
+
+#: ../Thuban/Model/classification.py:336
+msgid "Fill"
+msgstr "Preenchimento"
+
+#: ../Thuban/Model/classification.py:342 ../Thuban/UI/classifier.py:841
+msgid "Classification"
+msgstr "Classificação"
+
+#: ../Thuban/Model/classification.py:436
+msgid "lineWidth < 1"
+msgstr "espessura da linha < 1"
+
+#: ../Thuban/Model/classification.py:451
+msgid "size < 1"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:656 ../Thuban/UI/classifier.py:528
+msgid "DEFAULT"
+msgstr "PADRÃO"
+
+#: ../Thuban/Model/data.py:316
+msgid "Table not compatible with shapestore."
+msgstr "Tabela não compatível com a base de shapes"
+
+#: ../Thuban/Model/extension.py:90
+#, python-format
+msgid "Extension: %s"
+msgstr "Extensão: %s"
+
+#: ../Thuban/Model/label.py:91
+#, fuzzy, python-format
+msgid "Number of labels: %d"
+msgstr "Número de Classes:"
+
+#: ../Thuban/Model/label.py:92
+#, fuzzy, python-format
+msgid "Label Layer: %s"
+msgstr "Tabela: %s"
+
+#: ../Thuban/Model/layer.py:298 ../Thuban/Model/layer.py:566
+#: ../Thuban/Model/session.py:432
+#, python-format
+msgid "Filename: %s"
+msgstr "Arquivo: %s"
+
+#: ../Thuban/Model/layer.py:301 ../Thuban/Model/layer.py:569
+msgid "Shown"
+msgstr "Visível"
+
+#: ../Thuban/Model/layer.py:303 ../Thuban/Model/layer.py:571
+msgid "Hidden"
+msgstr "Oculto"
+
+#: ../Thuban/Model/layer.py:304
+#, python-format
+msgid "Shapes: %d"
+msgstr "Shapes: %d"
+
+#: ../Thuban/Model/layer.py:308 ../Thuban/Model/layer.py:575
+#: ../Thuban/Model/map.py:287 ../Thuban/UI/rasterlayerproperties.py:51
+#, python-format
+msgid "Extent (lat-lon): (%g, %g, %g, %g)"
+msgstr "Retângulo envolvente (lat-lon): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/layer.py:310 ../Thuban/Model/layer.py:577
+msgid "Extent (lat-lon):"
+msgstr "Retângulo envolvente (lat-lon):"
+
+#: ../Thuban/Model/layer.py:311
+#, python-format
+msgid "Shapetype: %s"
+msgstr "Tipo de Shape: %s"
+
+#: ../Thuban/Model/layer.py:314 ../Thuban/Model/layer.py:580
+#: ../Thuban/Model/map.py:292
+msgid "Projection"
+msgstr "Projeção"
+
+#: ../Thuban/Model/layer.py:319 ../Thuban/Model/layer.py:583
+#, python-format
+msgid "Layer '%s'"
+msgstr "Camada '%s'"
+
+#: ../Thuban/Model/load.py:78
+#, python-format
+msgid "Invalid hexadecimal color specification %s"
+msgstr "Especificação de cor hexadecimal inválida %s"
+
+#: ../Thuban/Model/load.py:81
+#, python-format
+msgid "Invalid color specification %s"
+msgstr "Especificação de cor inválida %s"
+
+#: ../Thuban/Model/load.py:544
+msgid "xml field type differs from database!"
+msgstr "tipo do campo xml difere do banco de dados"
+
+#: ../Thuban/Model/load.py:609
+msgid "Classification range is not a number!"
+msgstr "Faixa de classificação não é um número"
+
+#: ../Thuban/Model/map.py:53
+msgid "Labels"
+msgstr "Rótulos"
+
+#: ../Thuban/Model/map.py:290
+#, python-format
+msgid "Extent (projected): (%g, %g, %g, %g)"
+msgstr "Retângulo envolvente (projetado): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/map.py:301
+#, python-format
+msgid "Map: %s"
+msgstr "Mapa: %s"
+
+#: ../Thuban/Model/proj.py:84 ../Thuban/Model/resource.py:179
+msgid "Unknown"
+msgstr "Desconhecido"
+
+#: ../Thuban/Model/resource.py:46
+#, python-format
+msgid ""
+"No GDAL support because module '%s' cannot be imported. Python exception: '%"
+"s'"
+msgstr ""
+"Sem suporte a GDAL porque o módulo '%s' não pôde ser importado. Python "
+"exception: '%s'"
+
+#: ../Thuban/Model/resource.py:135 ../Thuban/Model/resource.py:155
+#, python-format
+msgid "Could not read \"%s\": %s"
+msgstr "Impossível ler \"%s\": %s"
+
+#: ../Thuban/Model/resource.py:187
+#, python-format
+msgid "Error in projection \"%s\": %s"
+msgstr "Erro na projeção \"%s\": %s"
+
+#: ../Thuban/Model/save.py:352
+msgid "Unsupported group type in classification"
+msgstr "Tipo de grupo não suportado na classificação"
+
+#: ../Thuban/Model/session.py:430
+msgid "Filename:"
+msgstr "Arquivo:"
+
+#: ../Thuban/Model/session.py:435
+msgid "Modified"
+msgstr "Modificado"
+
+#: ../Thuban/Model/session.py:437
+msgid "Unmodified"
+msgstr "Não modificado"
+
+#: ../Thuban/Model/session.py:442
+#, python-format
+msgid "Session: %s"
+msgstr "Sessão: %s"
+
+#: ../Thuban/Model/session.py:448
+msgid "unnamed session"
+msgstr "sessão sem nome"
+
+#: ../Thuban/Model/session.py:450
+msgid "unnamed map"
+msgstr "map sem nome"
+
+#: ../Thuban/UI/about.py:28
+msgid "About Thuban"
+msgstr "Sobre o Thuban"
+
+#: ../Thuban/UI/about.py:47
+msgid "French"
+msgstr "Francês"
+
+#: ../Thuban/UI/about.py:48
+msgid "German"
+msgstr "Alemão"
+
+#: ../Thuban/UI/about.py:50
+msgid "Hungarian"
+msgstr ""
+
+#: ../Thuban/UI/about.py:51
+msgid "Italian"
+msgstr "Italiano"
+
+#: ../Thuban/UI/about.py:52
+msgid "Portuguese (Brazilian)"
+msgstr ""
+
+#: ../Thuban/UI/about.py:53
+msgid "Russian"
+msgstr "Russo"
+
+#: ../Thuban/UI/about.py:54
+msgid "Spanish"
+msgstr "Espanhol"
+
+#: ../Thuban/UI/about.py:63 ../Thuban/UI/about.py:65 ../Thuban/UI/about.py:67
+msgid "- not available"
+msgstr "- não disponível"
+
+#: ../Thuban/UI/about.py:72
+msgid "Currently using:\n"
+msgstr "Atualmente usando:\n"
+
+#: ../Thuban/UI/about.py:78
+#, python-format
+msgid "\tInternal encoding: %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:84
+msgid "Compiled for:\n"
+msgstr "Compilador por:\n"
+
+#: ../Thuban/UI/about.py:90
+#, fuzzy
+msgid "Extensions:\n"
+msgstr "Extensão: %s"
+
+#: ../Thuban/UI/about.py:95 ../Thuban/UI/about.py:144
+msgid "\tNone registered.\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:98
+msgid "Maintainers:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:103
+msgid "Lead Developer:\n"
+msgstr "Programador líder:\n"
+
+#: ../Thuban/UI/about.py:106
+msgid "Developers:\n"
+msgstr "Programadores:\n"
+
+#: ../Thuban/UI/about.py:111
+msgid "Translators:\n"
+msgstr "Tradutores:\n"
+
+#: ../Thuban/UI/about.py:116
+msgid "Other Contributors:\n"
+msgstr "Outros contribuintes:\n"
+
+#: ../Thuban/UI/about.py:122
+#, fuzzy
+msgid ""
+"Questions and comments can be sent to the following addresses:\n"
+"\tGeneral list (public):\n"
+"\t\t<thuban-list at intevation.de>\n"
+"\tDevelopers list (public):\n"
+"\t\t<thuban-devel at intevation.de>\n"
+"\tThuban team at Intevation:\n"
+"\t\t<thuban at intevation.de>\n"
+msgstr ""
+"Questões e comentários podem ser enviados aos seguintes endereços:\n"
+"\tProgramadores do Thuban:\n"
+"\t\t<thuban at intevation.de>\n"
+"\tLista de discussão Thuban:\n"
+"\t\t<thuban-list at intevation.de>"
+
+#: ../Thuban/UI/about.py:130
+msgid ""
+"Details on the registered extensions:\n"
+"\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:135
+#, python-format
+msgid "Copyright %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:136
+msgid "Authors:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:149
+msgid ""
+"Thuban is a program for exploring geographic data.\n"
+"\n"
+msgstr ""
+"O Thuban é um programa para exploração de dados geográficos.\n"
+"\n"
+
+#: ../Thuban/UI/about.py:151
+msgid "Thuban is licensed under the GNU GPL"
+msgstr "O Thuban é licensiado sobre os termos da GNU GPL"
+
+#: ../Thuban/UI/about.py:160 ../Thuban/UI/classgen.py:91
+#: ../Thuban/UI/dbdialog.py:276 ../Thuban/UI/dock.py:371
+#: ../Thuban/UI/join.py:66 ../Thuban/UI/layerproperties.py:82
+#: ../Thuban/UI/projdialog.py:209 ../Thuban/UI/tableview.py:388
+msgid "Close"
+msgstr "Fechar"
+
+#: ../Thuban/UI/altpathdialog.py:24
+#, fuzzy, python-format
+msgid "Select an alternative data file for %s"
+msgstr "Selecione um ou mais arquivos"
+
+#: ../Thuban/UI/altpathdialog.py:31 ../Thuban/UI/mainwindow.py:563
+msgid "Shapefiles (*.shp)"
+msgstr "Shapefiles (*.shp)"
+
+#: ../Thuban/UI/altpathdialog.py:32 ../Thuban/UI/mainwindow.py:564
+#: ../Thuban/UI/mainwindow.py:852
+msgid "All Files (*.*)"
+msgstr "Todos arquivos (*.*)"
+
+#: ../Thuban/UI/altpathdialog.py:47
+#, python-format
+msgid ""
+"Found the following as an alternative for %s.\n"
+"%s\n"
+"\n"
+" Please confirm with Yes or select alternative with No."
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:49
+msgid "Alternative Path"
+msgstr ""
+
+#: ../Thuban/UI/application.py:110 ../Thuban/UI/application.py:122
+msgid "Cannot import the thubanstart module\n"
+msgstr "Impossível importar o módulo thubanstart\n"
+
+#: ../Thuban/UI/application.py:115
+msgid "No thubanstart module available\n"
+msgstr "Módulo thubanstart não disponível\n"
+
+#: ../Thuban/UI/application.py:126
+msgid "No ~/.thuban directory\n"
+msgstr "Diretório ~/.thuban não encontrado\n"
+
+#: ../Thuban/UI/application.py:166
+msgid ""
+"This is the wxPython-based Graphical User Interface for exploring geographic "
+"data"
+msgstr ""
+"Este programa é uma Interface Gráfica de Usuário, baseado no wxPython, para "
+"exploração de dados geográficos"
+
+#: ../Thuban/UI/application.py:254
+msgid ""
+"The current session contains Image layers,\n"
+"but the GDAL library is not available to draw them."
+msgstr ""
+"A sessão atual contém camadas de Imagens,\n"
+"todavia a biblioteca GDAL não está disponível para desenhá-los."
+
+#: ../Thuban/UI/application.py:259
+msgid "Library not available"
+msgstr "Biblioteca não disponível"
+
+#: ../Thuban/UI/application.py:268 ../Thuban/UI/mainwindow.py:476
+msgid "DB Connection Parameters"
+msgstr "Parâmetros de Conexão com o Banco de Dados"
+
+#: ../Thuban/UI/application.py:364
+#, python-format
+msgid ""
+"An unhandled exception occurred:\n"
+"%s\n"
+"(please report to http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+msgstr ""
+"Uma exceção não prevista ocorreu:\n"
+"%s\n"
+"(por favor reporte o erro em http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/classgen.py:43
+msgid "Uniform Distribution"
+msgstr "Distribuição uniforma"
+
+#: ../Thuban/UI/classgen.py:44
+msgid "Unique Values"
+msgstr "Valores únicos"
+
+#: ../Thuban/UI/classgen.py:45
+msgid "Quantiles from Table"
+msgstr "Quantis da Tabela"
+
+#: ../Thuban/UI/classgen.py:47
+msgid "Custom Ramp"
+msgstr "Graduação Customizada"
+
+#: ../Thuban/UI/classgen.py:48
+msgid "Grey Ramp"
+msgstr "Graduação Cinza"
+
+#: ../Thuban/UI/classgen.py:49
+msgid "Red Ramp"
+msgstr "Graduação Vermelho"
+
+#: ../Thuban/UI/classgen.py:50
+msgid "Green Ramp"
+msgstr "Graduação Verde"
+
+#: ../Thuban/UI/classgen.py:51
+msgid "Blue Ramp"
+msgstr "Graduação Azul"
+
+#: ../Thuban/UI/classgen.py:52
+msgid "Green-to-Red Ramp"
+msgstr "Graduação Verde-para-Vermelho"
+
+#: ../Thuban/UI/classgen.py:53
+msgid "Hot-to-Cold Ramp"
+msgstr "Graduação Quente-para-Frio"
+
+#: ../Thuban/UI/classgen.py:69
+msgid "Generate Classification"
+msgstr "Criar Classificação"
+
+#: ../Thuban/UI/classgen.py:90
+msgid "Generate"
+msgstr "Criar"
+
+#: ../Thuban/UI/classgen.py:119
+#, python-format
+msgid "Field: %s"
+msgstr "Campo: %s"
+
+#: ../Thuban/UI/classgen.py:123 ../Thuban/UI/classifier.py:976
+#, python-format
+msgid "Data Type: %s"
+msgstr "Tipo de Dados: %s"
+
+#: ../Thuban/UI/classgen.py:127
+msgid "Generate:"
+msgstr "Criar:"
+
+#: ../Thuban/UI/classgen.py:137
+msgid "Color Scheme:"
+msgstr "Esquema de Cores:"
+
+#: ../Thuban/UI/classgen.py:161
+msgid "Fix Border Color"
+msgstr "Cor da Borda Fixa"
+
+#: ../Thuban/UI/classgen.py:168 ../Thuban/UI/classgen.py:936
+#: ../Thuban/UI/classgen.py:967
+msgid "Change"
+msgstr "Alterar"
+
+#: ../Thuban/UI/classgen.py:274
+msgid ""
+"Based on the data from the table and the input\n"
+"values, the exact quantiles could not be generated.\n"
+"\n"
+"Accept a close estimate?"
+msgstr ""
+"Com base nos dados da tabela e nos values\n"
+"de entrada, os quantis exatos não puderam ser criados.\n"
+"\n"
+"Aceitar um estimativa próxima?"
+
+#: ../Thuban/UI/classgen.py:277
+msgid "Problem with Quantiles"
+msgstr "Problema com os Quantis"
+
+#: ../Thuban/UI/classgen.py:370
+msgid "Min:"
+msgstr "Mín:"
+
+#: ../Thuban/UI/classgen.py:375
+msgid "Max:"
+msgstr "Máx:"
+
+#: ../Thuban/UI/classgen.py:380 ../Thuban/UI/classgen.py:633
+msgid "Retrieve From Table"
+msgstr "Recuperar da Tabela"
+
+#: ../Thuban/UI/classgen.py:390
+msgid "Number of Groups:"
+msgstr "Número de Grupos:"
+
+#: ../Thuban/UI/classgen.py:397
+msgid "Stepping:"
+msgstr "Incremento:"
+
+#: ../Thuban/UI/classgen.py:647
+#, fuzzy
+msgid "Available"
+msgstr "- não disponível"
+
+#: ../Thuban/UI/classgen.py:652 ../Thuban/UI/classgen.py:692
+msgid "Sort"
+msgstr "Ordenar"
+
+#: ../Thuban/UI/classgen.py:655 ../Thuban/UI/classgen.py:695
+msgid "Reverse"
+msgstr "Contrário"
+
+#: ../Thuban/UI/classgen.py:687
+#, fuzzy
+msgid "Use"
+msgstr "Usuário:"
+
+#: ../Thuban/UI/classgen.py:832
+msgid "Retrieve from Table"
+msgstr "Recuperar da Tabela"
+
+#: ../Thuban/UI/classgen.py:840
+msgid "Apply to Range"
+msgstr "Aplicar para a Faixa"
+
+#: ../Thuban/UI/classgen.py:847
+msgid "Number of Classes:"
+msgstr "Número de Classes:"
+
+#: ../Thuban/UI/classgen.py:930
+msgid "Start:"
+msgstr "Início:"
+
+#: ../Thuban/UI/classgen.py:961
+msgid "End:"
+msgstr "Fim:"
+
+#: ../Thuban/UI/classifier.py:164
+msgid "The Default group cannot be removed."
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:309
+#: ../Thuban/UI/classifier.py:467
+msgid "Pattern"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:306
+#: ../Thuban/UI/classifier.py:466
+msgid "Singleton"
+msgstr "Curinga"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Visible"
+msgstr "Visível"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Symbol"
+msgstr "Símbolo"
+
+#: ../Thuban/UI/classifier.py:317 ../Thuban/UI/controls.py:33
+#: ../Thuban/UI/controls.py:177
+msgid "Value"
+msgstr "Valor"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Label"
+msgstr "Rótulo"
+
+#: ../Thuban/UI/classifier.py:462 ../Thuban/UI/classifier.py:465
+msgid "Default"
+msgstr "Padrão"
+
+#: ../Thuban/UI/classifier.py:468
+msgid "Range"
+msgstr "Faixa"
+
+#: ../Thuban/UI/classifier.py:469
+msgid "Map"
+msgstr "Mapa"
+
+#: ../Thuban/UI/classifier.py:759
+msgid "Text"
+msgstr "Texto"
+
+#: ../Thuban/UI/classifier.py:760
+msgid "Integer"
+msgstr "Inteiro"
+
+#: ../Thuban/UI/classifier.py:761
+msgid "Decimal"
+msgstr "Decimal"
+
+#: ../Thuban/UI/classifier.py:820
+msgid "Generate Class"
+msgstr "Criar Classe"
+
+#: ../Thuban/UI/classifier.py:822 ../Thuban/UI/dbdialog.py:274
+msgid "Add"
+msgstr "Adicionar"
+
+#: ../Thuban/UI/classifier.py:824
+msgid "Move Up"
+msgstr "Mover para Cima"
+
+#: ../Thuban/UI/classifier.py:826
+msgid "Move Down"
+msgstr "Mover para Baixo"
+
+#: ../Thuban/UI/classifier.py:828
+msgid "Edit Symbol"
+msgstr "Editar Símbolo"
+
+#: ../Thuban/UI/classifier.py:830 ../Thuban/UI/dbdialog.py:275
+#: ../Thuban/UI/projdialog.py:117
+msgid "Remove"
+msgstr "Remover"
+
+#: ../Thuban/UI/classifier.py:845
+msgid "Field: "
+msgstr "Campo: "
+
+#: ../Thuban/UI/classifier.py:1000 ../Thuban/UI/layerproperties.py:160
+msgid "Layer Properties"
+msgstr "Propriedades da Camada"
+
+#: ../Thuban/UI/classifier.py:1167
+msgid "Select Properties"
+msgstr "Selecionar Propriedades"
+
+#: ../Thuban/UI/classifier.py:1178
+msgid "Preview:"
+msgstr "Pré-visualizar:"
+
+#: ../Thuban/UI/classifier.py:1195
+msgid "Change Line Color"
+msgstr "Alterar Cor da Linha"
+
+#: ../Thuban/UI/classifier.py:1201 ../Thuban/UI/classifier.py:1216
+msgid "Transparent"
+msgstr "Transparente"
+
+#: ../Thuban/UI/classifier.py:1212
+msgid "Change Fill Color"
+msgstr "Alterar Cor do Preenchimento"
+
+#: ../Thuban/UI/classifier.py:1225
+msgid "Line Width: "
+msgstr "Espessura da Linha:"
+
+#: ../Thuban/UI/classifier.py:1242
+#, fuzzy
+msgid "Size: "
+msgstr "Título: "
+
+#: ../Thuban/UI/classifier.py:1262 ../Thuban/UI/colordialog.py:52
+#: ../Thuban/UI/dbdialog.py:107 ../Thuban/UI/dbdialog.py:221
+#: ../Thuban/UI/labeldialog.py:41 ../Thuban/UI/layerproperties.py:81
+#: ../Thuban/UI/projdialog.py:205
+msgid "OK"
+msgstr "OK"
+
+#: ../Thuban/UI/classifier.py:1264 ../Thuban/UI/colordialog.py:53
+#: ../Thuban/UI/dbdialog.py:110 ../Thuban/UI/dbdialog.py:223
+#: ../Thuban/UI/labeldialog.py:42 ../Thuban/UI/projdialog.py:1033
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: ../Thuban/UI/colordialog.py:39
+#, fuzzy
+msgid "Select Color"
+msgstr "Seleção"
+
+#: ../Thuban/UI/controls.py:31
+msgid "Field"
+msgstr "Campo"
+
+#: ../Thuban/UI/dbdialog.py:41
+msgid "Choose layer from database"
+msgstr "Selecione a camada do banco de dados"
+
+#: ../Thuban/UI/dbdialog.py:59
+msgid "Databases"
+msgstr "Bancos de Dados"
+
+#: ../Thuban/UI/dbdialog.py:74
+msgid "Retrieve"
+msgstr "Recuperar"
+
+#: ../Thuban/UI/dbdialog.py:82
+msgid "Tables"
+msgstr "Tabelas"
+
+#: ../Thuban/UI/dbdialog.py:92
+msgid "ID Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:98
+msgid "Geometry Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:187
+msgid "Hostname:"
+msgstr "Nome do servidor:"
+
+#: ../Thuban/UI/dbdialog.py:191
+msgid "Port:"
+msgstr "Porta:"
+
+#: ../Thuban/UI/dbdialog.py:198
+msgid "Database Name:"
+msgstr "Nome do Banco de Dados:"
+
+#: ../Thuban/UI/dbdialog.py:206
+msgid "User:"
+msgstr "Usuário:"
+
+#: ../Thuban/UI/dbdialog.py:211
+msgid "Password:"
+msgstr "Senha:"
+
+#: ../Thuban/UI/dbdialog.py:286
+msgid "Database Management"
+msgstr "Gerenciamento de Banco de Dados"
+
+#: ../Thuban/UI/dbdialog.py:361 ../Thuban/UI/dbdialog.py:366
+msgid "Add Database"
+msgstr "Adicionar Banco de Dados"
+
+#: ../Thuban/UI/dbdialog.py:367
+#, python-format
+msgid "Connection '%s' already exists"
+msgstr "A Conexão '%s' já existe"
+
+#: ../Thuban/UI/dbdialog.py:388
+msgid "Remove Database Connection"
+msgstr "Remover Conexão com Banco de Dados"
+
+#: ../Thuban/UI/dbdialog.py:389
+#, python-format
+msgid ""
+"The connection %s\n"
+"is still in use"
+msgstr ""
+"A conexão %s\n"
+"ainda está em uso"
+
+#: ../Thuban/UI/dock.py:190
+msgid "Undock"
+msgstr "Desancorar"
+
+#: ../Thuban/UI/dock.py:218
+msgid "Dock"
+msgstr "Ancorar"
+
+#: ../Thuban/UI/exceptiondialog.py:23 ../Thuban/UI/exceptiondialog.py:61
+msgid "Thuban: Internal Error"
+msgstr "Thuban: Erro Interno"
+
+#: ../Thuban/UI/exceptiondialog.py:43
+msgid "Proceed"
+msgstr "Prosseguir"
+
+#: ../Thuban/UI/exceptiondialog.py:44
+msgid "Exit Thuban now"
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:72
+msgid "Initialization not yet requested."
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:88
+msgid "Initialization successful."
+msgstr ""
+
+#: ../Thuban/UI/identifyview.py:44
+msgid "Identify Shape"
+msgstr "Identificar Item"
+
+#: ../Thuban/UI/identifyview.py:56
+msgid "Close Window"
+msgstr "Fechar Janela"
+
+#: ../Thuban/UI/identifyview.py:57
+msgid "Stop Identify Mode"
+msgstr "Para modo de identificação"
+
+#: ../Thuban/UI/join.py:64
+msgid "Join"
+msgstr "Ligação"
+
+#: ../Thuban/UI/join.py:71 ../Thuban/UI/join.py:72
+msgid "Select..."
+msgstr "Selecione..."
+
+#: ../Thuban/UI/join.py:100 ../Thuban/UI/join.py:108
+msgid "Table:"
+msgstr "Tabela:"
+
+#: ../Thuban/UI/join.py:111 ../Thuban/UI/join.py:114
+msgid "Field:"
+msgstr "Campo:"
+
+#: ../Thuban/UI/join.py:125
+msgid "Outer Join (preserves left table records)"
+msgstr "Outer Join (preserva os registros da tabela da esquerda)"
+
+#: ../Thuban/UI/join.py:173
+#, python-format
+msgid ""
+"Join failed:\n"
+"  %s"
+msgstr ""
+"Ligação falhou:\n"
+"  %s"
+
+#: ../Thuban/UI/join.py:174
+msgid "Info"
+msgstr "Informação"
+
+#: ../Thuban/UI/join.py:195
+#, python-format
+msgid ""
+"The joined table has %(joined)d rows but it must have %(needed)d rows to be "
+"used with the selected layer"
+msgstr ""
+"A tabela ligada(joined) possui %(joined)d registros mas deve ter %(needed)d "
+"registros para serusada com a camada selecionada"
+
+#: ../Thuban/UI/join.py:200
+msgid "Join Failed"
+msgstr "Ligação Falhou"
+
+#: ../Thuban/UI/join.py:209 ../Thuban/UI/mainwindow.py:915
+#, python-format
+msgid "Table: %s"
+msgstr "Tabela: %s"
+
+#: ../Thuban/UI/labeldialog.py:26
+msgid "Label Values"
+msgstr "Valores dos Rótulos"
+
+#: ../Thuban/UI/layerproperties.py:54
+msgid "Title: "
+msgstr "Título: "
+
+#: ../Thuban/UI/layerproperties.py:65
+#, fuzzy, python-format
+msgid "Layer Type: %s"
+msgstr "Tabela da Camada: %s"
+
+#: ../Thuban/UI/layerproperties.py:71
+#, fuzzy
+msgid "Projection: None"
+msgstr "Projeção:"
+
+#: ../Thuban/UI/layerproperties.py:73
+#, fuzzy, python-format
+msgid "Projection: %s"
+msgstr "Projeção:"
+
+#: ../Thuban/UI/layerproperties.py:79 ../Thuban/UI/projdialog.py:199
+msgid "Try"
+msgstr "Tentar"
+
+#: ../Thuban/UI/layerproperties.py:80 ../Thuban/UI/projdialog.py:202
+msgid "Revert"
+msgstr "Reverter"
+
+#: ../Thuban/UI/legend.py:75
+msgid "Top Layer"
+msgstr "Camada Superior"
+
+#: ../Thuban/UI/legend.py:79
+msgid "Raise Layer"
+msgstr "Trazer Camada para cima"
+
+#: ../Thuban/UI/legend.py:83
+msgid "Lower Layer"
+msgstr "Trazer Camada para baixo"
+
+#: ../Thuban/UI/legend.py:87
+msgid "Bottom Layer"
+msgstr "Camada Inferior"
+
+#: ../Thuban/UI/legend.py:91
+msgid "Show Layer"
+msgstr "Exibir Camada"
+
+#: ../Thuban/UI/legend.py:95
+msgid "Hide Layer"
+msgstr "Ocultar Camada"
+
+#: ../Thuban/UI/legend.py:99
+msgid "Edit Layer Properties"
+msgstr "Editar Propriedades da Camada"
+
+#: ../Thuban/UI/mainwindow.py:264 ../Thuban/UI/mainwindow.py:286
+#, python-format
+msgid "Unknown command %s"
+msgstr "Comando desconhecido %s"
+
+#: ../Thuban/UI/mainwindow.py:299
+#, python-format
+msgid "Unknown command ID %d"
+msgstr "ID de comando desconhecido %d"
+
+#: ../Thuban/UI/mainwindow.py:338
+#, python-format
+msgid "The Dialog named %s is already open"
+msgstr "A caixa de Diálog %s ainda está aberta"
+
+#: ../Thuban/UI/mainwindow.py:396
+#, python-format
+msgid "Select layer '%s' and pick a projection using Layer/Projection..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:449
+msgid "Exit"
+msgstr "Sair"
+
+#: ../Thuban/UI/mainwindow.py:450
+msgid "The session has been modified. Do you want to save it?"
+msgstr "A sessão foi modificada. Você deseja salvá-la?"
+
+#: ../Thuban/UI/mainwindow.py:465
+msgid "Open Session"
+msgstr "Abrir Sessão"
+
+#: ../Thuban/UI/mainwindow.py:487
+msgid "Save Session As"
+msgstr "Salvar Sessão como"
+
+#: ../Thuban/UI/mainwindow.py:561
+msgid "Select one or more data files"
+msgstr "Selecione um ou mais arquivos"
+
+#: ../Thuban/UI/mainwindow.py:576
+msgid "Add Layer"
+msgstr "Adicionar Camada"
+
+#: ../Thuban/UI/mainwindow.py:577 ../Thuban/UI/mainwindow.py:602
+#: ../Thuban/UI/mainwindow.py:862
+#, python-format
+msgid "Can't open the file '%s'."
+msgstr "Não foi possível abrir o arquivo '%s'."
+
+#: ../Thuban/UI/mainwindow.py:589
+msgid "Select an image file"
+msgstr "Selecione um arquivo de imagem"
+
+#: ../Thuban/UI/mainwindow.py:601
+msgid "Add Image Layer"
+msgstr "Adicionar Camada de Imagem"
+
+#: ../Thuban/UI/mainwindow.py:629
+msgid "Add Layer from database"
+msgstr "Adicionar Camada do banco de dados"
+
+#: ../Thuban/UI/mainwindow.py:630
+#, python-format
+msgid "Can't open the database table '%s'"
+msgstr "Não foi possível abrir a tabela '%s'"
+
+#: ../Thuban/UI/mainwindow.py:719
+#, python-format
+msgid "Copy of `%s'"
+msgstr "Cópia de `%s'"
+
+#: ../Thuban/UI/mainwindow.py:749
+#, python-format
+msgid "Layer Table: %s"
+msgstr "Tabela da Camada: %s"
+
+#: ../Thuban/UI/mainwindow.py:764
+#, python-format
+msgid "Map Projection: %s"
+msgstr "Projeção do Mapa: %s"
+
+#: ../Thuban/UI/mainwindow.py:779
+#, python-format
+msgid "Layer Projection: %s"
+msgstr "Projeção do Layer: %s"
+
+#: ../Thuban/UI/mainwindow.py:812
+msgid "Join Layer with Table"
+msgstr "Ligar Camada com Tabela"
+
+#: ../Thuban/UI/mainwindow.py:834 ../Thuban/UI/mainwindow.py:1165
+msgid "Legend"
+msgstr "Legenda"
+
+#: ../Thuban/UI/mainwindow.py:848 ../Thuban/UI/mainwindow.py:861
+msgid "Open Table"
+msgstr "Abrir Tabela"
+
+#: ../Thuban/UI/mainwindow.py:850
+msgid "DBF Files (*.dbf)"
+msgstr "Arquivos DBF (*.dbf)"
+
+#: ../Thuban/UI/mainwindow.py:873
+msgid "Pick the tables to close:"
+msgstr "Escolha as tabelas para fechar:"
+
+#: ../Thuban/UI/mainwindow.py:874
+msgid "Close Table"
+msgstr "Fechar Tabela"
+
+#: ../Thuban/UI/mainwindow.py:894
+msgid "Pick the table to show:"
+msgstr "Escolha a tabela para exibir:"
+
+#: ../Thuban/UI/mainwindow.py:895
+msgid "Show Table"
+msgstr "Exibir Tabela"
+
+#: ../Thuban/UI/mainwindow.py:906
+msgid "Join Tables"
+msgstr "Ligar Tabelas"
+
+#: ../Thuban/UI/mainwindow.py:929
+msgid "Pick the table to rename:"
+msgstr "Escolha a tabela a renomear:"
+
+#: ../Thuban/UI/mainwindow.py:930 ../Thuban/UI/mainwindow.py:942
+msgid "Rename Table"
+msgstr "Renomear Tabela"
+
+#: ../Thuban/UI/mainwindow.py:942
+msgid "Table Title:"
+msgstr "Título da Tabela:"
+
+#: ../Thuban/UI/mainwindow.py:991
+msgid "Map Title:"
+msgstr "Título do Mapa:"
+
+#: ../Thuban/UI/mainwindow.py:991
+msgid "Rename Map"
+msgstr "Renomear Mapa"
+
+#: ../Thuban/UI/mainwindow.py:1004
+msgid "Layer Title:"
+msgstr "Título da Camada:"
+
+#: ../Thuban/UI/mainwindow.py:1004
+msgid "Rename Layer"
+msgstr "Renomear Camada"
+
+#: ../Thuban/UI/mainwindow.py:1057
+#, python-format
+msgid "Thuban - %s"
+msgstr "Thuban - %s"
+
+#: ../Thuban/UI/mainwindow.py:1059
+msgid "Thuban"
+msgstr "Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1154
+msgid "&New Session"
+msgstr "&Nova Sessão"
+
+#: ../Thuban/UI/mainwindow.py:1155
+msgid "Start a new session"
+msgstr "Iniciar uma nova sessão"
+
+#: ../Thuban/UI/mainwindow.py:1156
+msgid "&Open Session..."
+msgstr "Abrir sessã&o"
+
+#: ../Thuban/UI/mainwindow.py:1157
+msgid "Open a session file"
+msgstr "Abrir um arquivo de sessão"
+
+#: ../Thuban/UI/mainwindow.py:1158
+msgid "&Save Session"
+msgstr "&Salvar Sessão"
+
+#: ../Thuban/UI/mainwindow.py:1159
+msgid "Save this session to the file it was opened from"
+msgstr "Salva esta sessão no arquivo que a abriu"
+
+#: ../Thuban/UI/mainwindow.py:1160
+msgid "Save Session &As..."
+msgstr "S&alvar Sessão como..."
+
+#: ../Thuban/UI/mainwindow.py:1161
+msgid "Save this session to a new file"
+msgstr "Salvar esta sessão em um novo arquivo"
+
+#: ../Thuban/UI/mainwindow.py:1162
+msgid "Session &Tree"
+msgstr "Árvore da Sessão"
+
+#: ../Thuban/UI/mainwindow.py:1164
+msgid "Toggle on/off the session tree analysis window"
+msgstr "Liga/Desliga a janela de análise da árvore de sessão"
+
+#: ../Thuban/UI/mainwindow.py:1167
+msgid "Toggle Legend on/off"
+msgstr "Liga/Desliga a Legenda"
+
+#: ../Thuban/UI/mainwindow.py:1168
+msgid "&Database Connections..."
+msgstr "Conexões com Banco de &Dados..."
+
+#: ../Thuban/UI/mainwindow.py:1171
+msgid "E&xit"
+msgstr "Sair"
+
+#: ../Thuban/UI/mainwindow.py:1172
+msgid "Finish working with Thuban"
+msgstr "Concluir trabalho com o Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1175
+msgid "&About..."
+msgstr "Sobre..."
+
+#: ../Thuban/UI/mainwindow.py:1176
+msgid "Info about Thuban authors, version and modules"
+msgstr "Informações sobre os autores do Thuban, versão e módulos"
+
+#: ../Thuban/UI/mainwindow.py:1180 ../Thuban/UI/mainwindow.py:1228
+msgid "Pro&jection..."
+msgstr "Pro&jeção..."
+
+#: ../Thuban/UI/mainwindow.py:1181
+msgid "Set or change the map projection"
+msgstr "Definir ou alterar a projeção do mapa"
+
+#: ../Thuban/UI/mainwindow.py:1183
+msgid "&Zoom in"
+msgstr "&Zoom in"
+
+#: ../Thuban/UI/mainwindow.py:1184
+msgid "Switch to map-mode 'zoom-in'"
+msgstr "Alterar para o modo de mapa 'zoom-in'"
+
+#: ../Thuban/UI/mainwindow.py:1186
+msgid "Zoom &out"
+msgstr "Zoom &out"
+
+#: ../Thuban/UI/mainwindow.py:1187
+msgid "Switch to map-mode 'zoom-out'"
+msgstr "Alterar para o modo de mapa 'zoom-out'"
+
+#: ../Thuban/UI/mainwindow.py:1189
+msgid "&Pan"
+msgstr "&Pan"
+
+#: ../Thuban/UI/mainwindow.py:1190
+msgid "Switch to map-mode 'pan'"
+msgstr "Alterar para o modo de mapa 'pan'"
+
+#: ../Thuban/UI/mainwindow.py:1192
+msgid "&Identify"
+msgstr "&Identificar"
+
+#: ../Thuban/UI/mainwindow.py:1194
+msgid "Switch to map-mode 'identify'"
+msgstr "Alterar para o modo de mapa 'identificar'"
+
+#: ../Thuban/UI/mainwindow.py:1196
+msgid "&Label"
+msgstr "Rótu&lo"
+
+#: ../Thuban/UI/mainwindow.py:1197
+msgid "Add/Remove labels"
+msgstr "Adicionar/Remover Rótulos"
+
+#: ../Thuban/UI/mainwindow.py:1199
+msgid "&Full extent"
+msgstr "Extensão total"
+
+#: ../Thuban/UI/mainwindow.py:1200
+msgid "Zoom to the full map extent"
+msgstr "Zoom para a extensão total do mapa"
+
+#: ../Thuban/UI/mainwindow.py:1202
+msgid "&Full layer extent"
+msgstr "Extensão total da camada"
+
+#: ../Thuban/UI/mainwindow.py:1203
+msgid "Zoom to the full layer extent"
+msgstr "Zoom para a extensão total da camada"
+
+#: ../Thuban/UI/mainwindow.py:1205
+msgid "&Full selection extent"
+msgstr "Extensão total da seleção"
+
+#: ../Thuban/UI/mainwindow.py:1207
+msgid "Zoom to the full selection extent"
+msgstr "Zoom para extensão total da seleção"
+
+#: ../Thuban/UI/mainwindow.py:1209
+msgid "E&xport"
+msgstr "E&xportar"
+
+#: ../Thuban/UI/mainwindow.py:1210
+msgid "Export the map to file"
+msgstr "Exportar o mapa para arquivo"
+
+#: ../Thuban/UI/mainwindow.py:1211
+msgid "Prin&t"
+msgstr "Imprimir"
+
+#: ../Thuban/UI/mainwindow.py:1212
+msgid "Print the map"
+msgstr "Imprimir o mapa"
+
+#: ../Thuban/UI/mainwindow.py:1213 ../Thuban/UI/mainwindow.py:1299
+msgid "&Rename..."
+msgstr "&Renomear..."
+
+#: ../Thuban/UI/mainwindow.py:1214
+msgid "Rename the map"
+msgstr "Renomear o mapa"
+
+#: ../Thuban/UI/mainwindow.py:1215
+msgid "&Add Layer..."
+msgstr "&Adicionar Camada..."
+
+#: ../Thuban/UI/mainwindow.py:1216
+msgid "Add a new layer to the map"
+msgstr "Adicionar uma nova camaada ao mapa"
+
+#: ../Thuban/UI/mainwindow.py:1217
+msgid "&Add Image Layer..."
+msgstr "&Adicionar Camada de Imagem..."
+
+#: ../Thuban/UI/mainwindow.py:1218
+msgid "Add a new image layer to the map"
+msgstr "Adicionar uma nova camada de imagem ao mapa"
+
+#: ../Thuban/UI/mainwindow.py:1220
+msgid "Add &Database Layer..."
+msgstr "Adicionar uma Camada de Banco de &Dados"
+
+#: ../Thuban/UI/mainwindow.py:1221
+msgid "Add a new database layer to active map"
+msgstr "Adicionar uma nova camada de banco de dados ao mapa ativo"
+
+#: ../Thuban/UI/mainwindow.py:1223
+msgid "&Remove Layer"
+msgstr "&Remover Camada"
+
+#: ../Thuban/UI/mainwindow.py:1224
+msgid "Remove selected layer"
+msgstr "Remover a camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1230
+msgid "Specify projection for selected layer"
+msgstr "Especifique a projeção para a camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1231
+msgid "&Duplicate"
+msgstr "&Duplicar"
+
+#: ../Thuban/UI/mainwindow.py:1232
+msgid "Duplicate selected layer"
+msgstr "Duplicar a camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1234
+msgid "Re&name ..."
+msgstr "Re&nomear ..."
+
+#: ../Thuban/UI/mainwindow.py:1235
+msgid "Rename selected layer"
+msgstr "Renomear a camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1237
+msgid "&Raise"
+msgstr "Traze&r para cima"
+
+#: ../Thuban/UI/mainwindow.py:1238
+msgid "Raise selected layer"
+msgstr "Trazer para cima a camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1240
+msgid "&Lower"
+msgstr "Trazer para baixo"
+
+#: ../Thuban/UI/mainwindow.py:1241
+msgid "Lower selected layer"
+msgstr "Trazer para baixo a camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1243
+msgid "&Show"
+msgstr "Exibir"
+
+#: ../Thuban/UI/mainwindow.py:1244
+msgid "Make selected layer visible"
+msgstr "Tornar a camada selecionada visível"
+
+#: ../Thuban/UI/mainwindow.py:1246
+msgid "&Hide"
+msgstr "Ocultar"
+
+#: ../Thuban/UI/mainwindow.py:1247
+msgid "Make selected layer unvisible"
+msgstr "Tornar a camada selecionada oculta"
+
+#: ../Thuban/UI/mainwindow.py:1249
+msgid "Show Ta&ble"
+msgstr "Exibir Ta&bela"
+
+#: ../Thuban/UI/mainwindow.py:1250
+msgid "Show the selected layer's table"
+msgstr "Exibir a tabela da camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1252
+msgid "&Properties..."
+msgstr "&Propriedades..."
+
+#: ../Thuban/UI/mainwindow.py:1254
+msgid "Edit the properties of the selected layer"
+msgstr "Editar as propriedades da camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1255
+msgid "&Join Table..."
+msgstr "Fazer ligação com Tabela..."
+
+#: ../Thuban/UI/mainwindow.py:1257
+msgid "Join and attach a table to the selected layer"
+msgstr "Fazer ligação e anexar uma tabela à camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1260
+msgid "&Top"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1261
+#, fuzzy
+msgid "Put selected layer to the top"
+msgstr "Duplicar a camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1263
+#, fuzzy
+msgid "&Bottom"
+msgstr "Camada Inferior"
+
+#: ../Thuban/UI/mainwindow.py:1264
+#, fuzzy
+msgid "Put selected layer to the bottom"
+msgstr "Duplicar a camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1266
+#, fuzzy
+msgid "&Visible"
+msgstr "Visível"
+
+#: ../Thuban/UI/mainwindow.py:1268
+#, fuzzy
+msgid "Toggle visibility of selected layer"
+msgstr "Trazer para cima a camada selecionada"
+
+#: ../Thuban/UI/mainwindow.py:1285
+msgid "&Unjoin Table..."
+msgstr "Desfazer ligação de tabela..."
+
+#: ../Thuban/UI/mainwindow.py:1287
+msgid "Undo the last join operation"
+msgstr "Desfazer a última operação de ligação"
+
+#: ../Thuban/UI/mainwindow.py:1294
+msgid "&Open..."
+msgstr "Abrir..."
+
+#: ../Thuban/UI/mainwindow.py:1295
+msgid "Open a DBF-table from a file"
+msgstr "Abrir uma tabela-DBF de um arquivo"
+
+#: ../Thuban/UI/mainwindow.py:1296
+msgid "&Close..."
+msgstr "Fechar..."
+
+#: ../Thuban/UI/mainwindow.py:1298
+msgid "Close one or more tables from a list"
+msgstr "Fechar uma ou mais tabela de uma lista"
+
+#: ../Thuban/UI/mainwindow.py:1301
+msgid "Rename one or more tables"
+msgstr "Renomear uma ou mais tabelas"
+
+#: ../Thuban/UI/mainwindow.py:1302
+msgid "&Show..."
+msgstr "Exibir"
+
+#: ../Thuban/UI/mainwindow.py:1304
+msgid "Show one or more tables in a dialog"
+msgstr "Exibir uma ou mais tabelas em um diálogo"
+
+#: ../Thuban/UI/mainwindow.py:1305
+msgid "&Join..."
+msgstr "Ligação..."
+
+#: ../Thuban/UI/mainwindow.py:1307
+msgid "Join two tables creating a new one"
+msgstr "Ligar duas tabelas criando uma nova"
+
+#: ../Thuban/UI/mainwindow.py:1331
+msgid "&File"
+msgstr "Arquivo"
+
+#: ../Thuban/UI/mainwindow.py:1337
+msgid "&Map"
+msgstr "&Mapa"
+
+#: ../Thuban/UI/mainwindow.py:1338
+msgid "&Layer"
+msgstr "Camada"
+
+#: ../Thuban/UI/mainwindow.py:1352
+msgid "&Table"
+msgstr "&Tabela"
+
+#: ../Thuban/UI/mainwindow.py:1358
+msgid "&Help"
+msgstr "Ajuda"
+
+#: ../Thuban/UI/menu.py:90
+#, python-format
+msgid "Submenu %s doesn't exist"
+msgstr "Submenu %s não existe"
+
+#: ../Thuban/UI/projdialog.py:62 ../Thuban/UI/projdialog.py:776
+msgid "Transverse Mercator"
+msgstr "Transversa de Mercator"
+
+#: ../Thuban/UI/projdialog.py:63 ../Thuban/UI/projdialog.py:842
+msgid "Universal Transverse Mercator"
+msgstr "Universal Transversa de Mercator"
+
+#: ../Thuban/UI/projdialog.py:64 ../Thuban/UI/projdialog.py:918
+msgid "Lambert Conic Conformal"
+msgstr "Lambert Cônica Conforme"
+
+#: ../Thuban/UI/projdialog.py:65 ../Thuban/UI/projdialog.py:66
+#: ../Thuban/UI/projdialog.py:968
+msgid "Geographic"
+msgstr "Geográfica"
+
+#: ../Thuban/UI/projdialog.py:110
+msgid "Import..."
+msgstr "Importar..."
+
+#: ../Thuban/UI/projdialog.py:113
+msgid "Export..."
+msgstr "Exportar..."
+
+#: ../Thuban/UI/projdialog.py:122
+msgid "Show EPSG:"
+msgstr "Exibir EPSG:"
+
+#: ../Thuban/UI/projdialog.py:124
+msgid "Normal"
+msgstr "Normal"
+
+#: ../Thuban/UI/projdialog.py:127
+msgid "Deprecated"
+msgstr "Não aprovada"
+
+#: ../Thuban/UI/projdialog.py:138
+msgid "Edit"
+msgstr "Editar"
+
+#: ../Thuban/UI/projdialog.py:148
+msgid "Name:"
+msgstr "Nome:"
+
+#: ../Thuban/UI/projdialog.py:156
+msgid "Projection:"
+msgstr "Projeção:"
+
+#: ../Thuban/UI/projdialog.py:167 ../Thuban/UI/projdialog.py:648
+msgid "<Unknown>"
+msgstr "<Desconhecida>"
+
+#: ../Thuban/UI/projdialog.py:183
+msgid "New"
+msgstr "Nova"
+
+#: ../Thuban/UI/projdialog.py:186
+msgid "Add to List"
+msgstr "Adicionar à Lista"
+
+#: ../Thuban/UI/projdialog.py:190
+msgid "Update"
+msgstr "Atualizar"
+
+#: ../Thuban/UI/projdialog.py:295
+#, python-format
+msgid ""
+"Warnings when reading \"%s\":\n"
+"\n"
+"%s"
+msgstr ""
+"Avisos ao ler \"%s\":\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/projdialog.py:306
+msgid "Import"
+msgstr "Importar"
+
+#: ../Thuban/UI/projdialog.py:319 ../Thuban/UI/projdialog.py:617
+msgid "Warnings"
+msgstr "Avisos"
+
+#: ../Thuban/UI/projdialog.py:337 ../Thuban/UI/tableview.py:386
+msgid "Export"
+msgstr "Exportar"
+
+#: ../Thuban/UI/projdialog.py:389
+msgid "The following error occured:\n"
+msgstr "O seguinte erro ocorreu:\n"
+
+#: ../Thuban/UI/projdialog.py:391
+msgid "Error"
+msgstr "Erro"
+
+#: ../Thuban/UI/projdialog.py:460
+msgid "No Projections selected"
+msgstr "Nenhuma Projeção selecionada"
+
+#: ../Thuban/UI/projdialog.py:470
+#, python-format
+msgid "Source of Projection: %s"
+msgstr "Fonte da Projeção: %s"
+
+#: ../Thuban/UI/projdialog.py:502
+msgid "Multiple Projections selected"
+msgstr "Múltiplas Projeções selecionadas"
+
+#: ../Thuban/UI/projdialog.py:649
+msgid "Airy"
+msgstr "Aérea"
+
+#: ../Thuban/UI/projdialog.py:650
+msgid "Bessel 1841"
+msgstr "Bessel 1841"
+
+#: ../Thuban/UI/projdialog.py:651
+msgid "Clarke 1866"
+msgstr "Clarke 1866"
+
+#: ../Thuban/UI/projdialog.py:652
+msgid "Clarke 1880"
+msgstr "Clarke 1880"
+
+#: ../Thuban/UI/projdialog.py:653
+msgid "GRS 1980 (IUGG, 1980)"
+msgstr "GRS 1980 (IUGG, 1980)"
+
+#: ../Thuban/UI/projdialog.py:654
+msgid "International 1909 (Hayford)"
+msgstr "International 1909 (Hayford)"
+
+#: ../Thuban/UI/projdialog.py:655
+msgid "WGS 84"
+msgstr "WGS 84"
+
+#: ../Thuban/UI/projdialog.py:667
+msgid "Ellipsoid:"
+msgstr "Elipsóide:"
+
+#: ../Thuban/UI/projdialog.py:716
+msgid ""
+"Thuban does not know the parameters\n"
+"for the current projection and cannot\n"
+"display a configuration panel.\n"
+"\n"
+"The unidentified set of parameters is:\n"
+"\n"
+msgstr ""
+"Thuban não reconhece os parâmetros\n"
+"para a atual projeção e não pode\n"
+"exibir um painel de configuração.\n"
+"\n"
+"O conjunto não identificado de parâmetros é:\n"
+"\n"
+
+#: ../Thuban/UI/projdialog.py:762
+msgid "Latitude:"
+msgstr "Latitude:"
+
+#: ../Thuban/UI/projdialog.py:764
+msgid "Longitude:"
+msgstr "Longitude:"
+
+#: ../Thuban/UI/projdialog.py:766 ../Thuban/UI/projdialog.py:910
+msgid "False Easting:"
+msgstr "Falso Leste:"
+
+#: ../Thuban/UI/projdialog.py:768 ../Thuban/UI/projdialog.py:912
+msgid "False Northing:"
+msgstr "Falso Norte:"
+
+#: ../Thuban/UI/projdialog.py:770
+msgid "Scale Factor:"
+msgstr "Fator de Escala:"
+
+#: ../Thuban/UI/projdialog.py:821
+msgid "Propose"
+msgstr "Sugestão"
+
+#: ../Thuban/UI/projdialog.py:823
+msgid "Southern Hemisphere"
+msgstr "Hemisfério Sul"
+
+#: ../Thuban/UI/projdialog.py:833
+msgid "Zone:"
+msgstr "Zona:"
+
+#: ../Thuban/UI/projdialog.py:870
+msgid "Can not propose: No bounding box found."
+msgstr "Impossível sugerir: Retângulo Envolvente não encontrado"
+
+#: ../Thuban/UI/projdialog.py:871 ../Thuban/UI/projdialog.py:1008
+msgid "Projection: Propose UTM Zone"
+msgstr "Projeção: Sugerir Zona UTM"
+
+#: ../Thuban/UI/projdialog.py:901
+msgid "Latitude of first standard parallel:"
+msgstr "Latitude do primeiro paralelo:"
+
+#: ../Thuban/UI/projdialog.py:904
+msgid "Latitude of second standard parallel:"
+msgstr "Latitude do segundo paralelo:"
+
+#: ../Thuban/UI/projdialog.py:906
+msgid "Central Meridian:"
+msgstr "Meridiano Central:"
+
+#: ../Thuban/UI/projdialog.py:908
+msgid "Latitude of origin:"
+msgstr "Latitude de origem:"
+
+#: ../Thuban/UI/projdialog.py:958
+msgid "Degrees"
+msgstr "Graus"
+
+#: ../Thuban/UI/projdialog.py:959
+msgid "Radians"
+msgstr "Radianos"
+
+#: ../Thuban/UI/projdialog.py:992
+msgid "Source Data is in: "
+msgstr "Fonte de dados está em:"
+
+#: ../Thuban/UI/projdialog.py:1021
+msgid "The current map extent center lies in UTM Zone"
+msgstr "O centro da extensão corrente do mapa fica na Zona UTM"
+
+#: ../Thuban/UI/projdialog.py:1031
+msgid "Take"
+msgstr "Take"
+
+#: ../Thuban/UI/projlist.py:51
+msgid "Available Projections"
+msgstr "Projeções disponíveis"
+
+#: ../Thuban/UI/projlist.py:112
+msgid "<None>"
+msgstr "<Nenhuma>"
+
+#: ../Thuban/UI/projlist.py:117
+#, python-format
+msgid "%s (current)"
+msgstr "%s (atual)"
+
+#: ../Thuban/UI/rasterlayerproperties.py:41
+msgid "GDAL image information unavailable. See About box for details."
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:49
+#, fuzzy
+msgid "Extent (lat-lon): None"
+msgstr "Retângulo envolvente (lat-lon):"
+
+#: ../Thuban/UI/rasterlayerproperties.py:56
+#, fuzzy
+msgid "Image Properties"
+msgstr "Propriedades da Camada"
+
+#: ../Thuban/UI/rasterlayerproperties.py:61
+#, python-format
+msgid "Source: %s"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:71
+#, fuzzy, python-format
+msgid "Driver: %s"
+msgstr "Campo: %s"
+
+#: ../Thuban/UI/rasterlayerproperties.py:74
+#, python-format
+msgid "Size: %ix%i"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:77
+#, fuzzy, python-format
+msgid "Number of Bands: %i"
+msgstr "Número de Classes:"
+
+#: ../Thuban/UI/rasterlayerproperties.py:93
+msgid "Mask Type"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:99
+msgid "Opacity:"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:381
+msgid "Replace Selection"
+msgstr "Substituir Seleção"
+
+#: ../Thuban/UI/tableview.py:382
+msgid "Refine Selection"
+msgstr "Refinar Seleção"
+
+#: ../Thuban/UI/tableview.py:383
+msgid "Add to Selection"
+msgstr "Adicionar à Seleção"
+
+#: ../Thuban/UI/tableview.py:385
+msgid "Query"
+msgstr "Pesquisar"
+
+#: ../Thuban/UI/tableview.py:387
+msgid "Export Selection"
+msgstr "Exportar Seleção"
+
+#: ../Thuban/UI/tableview.py:413
+msgid "Selection"
+msgstr "Seleção"
+
+#: ../Thuban/UI/tableview.py:455
+#, python-format
+msgid "%i rows (%i selected), %i columns"
+msgstr "%i registros (%i selecionados), %i colunas"
+
+#: ../Thuban/UI/tableview.py:535
+msgid "Export Table To"
+msgstr "Exportar Tabela para"
+
+#: ../Thuban/UI/tableview.py:536
+msgid "DBF Files (*.dbf)|*.dbf|"
+msgstr "Arquivos DBF (*.dbf)|*.dbf|"
+
+#: ../Thuban/UI/tableview.py:537
+msgid "CSV Files (*.csv)|*.csv|"
+msgstr "Arquivos CSV (*.csv)|*.csv|"
+
+#: ../Thuban/UI/tableview.py:538
+msgid "All Files (*.*)|*.*"
+msgstr "Todos arquivos (*.*)|*.*"
+
+#: ../Thuban/UI/tree.py:226
+msgid "Session"
+msgstr "Sessão"
+
+#: ../Thuban/UI/view.py:285
+msgid "Export Map"
+msgstr "Exportar Mapa"
+
+#~ msgid "Type: %s"
+#~ msgstr "Tipo: %s"
+
+#~ msgid "Projection: UTM Parameters"
+#~ msgstr "Projeção: Parâmetros UTM"
+
+#~ msgid "UTM Zone"
+#~ msgstr "Zona UTM"
+
+#~ msgid "Ellipsoid"
+#~ msgstr "Elipsóide"

Added: packages/thuban/branches/upstream/current/po/ru.po
===================================================================
--- packages/thuban/branches/upstream/current/po/ru.po	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/po/ru.po	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1851 @@
+# Russian Translations for Thuban
+# Copyright (C) 2003 Alex Shevlakov
+# This file is distributed under the same license as the PACKAGE package.
+# Alex Shevlakov <alex at motivation.ru>
+msgid ""
+msgstr ""
+"Project-Id-Version: Thuban 0.9.0 CVS\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-03-13 20:15+0000\n"
+"PO-Revision-Date: 2003-12-26 12:00+0400\n"
+"Last-Translator: Alex Shevlakov <alex at motivation.ru>\n"
+"Language-Team: RU\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=koi8-r\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../Thuban/version.py:189
+#, python-format
+msgid "%s %s < %s"
+msgstr "%s %s < %s"
+
+#: ../Thuban/version.py:195
+#, python-format
+msgid "Thuban was compiled with wx %(wxproj-wx)s but wxPython is %(wxPython)s"
+msgstr ""
+
+#: ../Thuban/Lib/connector.py:65
+#, python-format
+msgid "no receivers for channel %s of %s"
+msgstr "ÎÅÔ ÐÒÉÅÍÎÉËÁ ÄÌÑ ËÁÎÁÌÁ %s ÉÚ %s"
+
+#: ../Thuban/Lib/connector.py:70
+#, python-format
+msgid "receiver %s%s is not connected to channel %s of %s"
+msgstr "ÐÒÉÅÍÎÉË %s%s ÎÅ ÓÏÅÄÉÎÅÎ Ó ËÁÎÁÌÏÍ %s ÉÚ %s"
+
+#: ../Thuban/Lib/connector.py:94
+#, python-format
+msgid "Warning: %s.%s: %s%s\n"
+msgstr "ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: %s.%s: %s%s\n"
+
+#: ../Thuban/Lib/connector.py:118
+#, python-format
+msgid "\tmethod %s of %s"
+msgstr "\tÍÅÔÏÄ %s ÉÚ %s"
+
+#: ../Thuban/Lib/fileutil.py:87 ../Thuban/Lib/fileutil.py:141
+msgid "first argument must be an absolute filename"
+msgstr "ÐÅÒ×ÙÍ ÁÒÇÕÍÅÎÔÏÍ ÄÏÌÖÅÎ ÂÙÔØ ÁÂÓÏÌÀÔÎÙÊ ÐÕÔØ Ë ÆÁÊÌÕ"
+
+#: ../Thuban/Lib/fileutil.py:138
+msgid "Both parameters must have a drive letter"
+msgstr "ïÂÁ ÐÁÒÁÍÅÔÒÁ ÄÏÌÖÎÙ ÉÍÅÔØ ÂÕË×Õ ÎÁÚ×ÁÎÉÑ ÖÅÓÔËÏÇÏ ÄÉÓËÁ"
+
+#: ../Thuban/Lib/fileutil.py:198
+msgid "No implementation of get_application_dir available for platform"
+msgstr "äÌÑ ÐÌÁÔÆÏÒÍÙ ÎÅ ×ÙÐÏÌÎÅÎ get_application_dir"
+
+#: ../Thuban/Lib/fileutil.py:208
+msgid "No implementation of relative_filename available for platform"
+msgstr "äÌÑ ÐÌÁÔÆÏÒÍÙ ÎÅ ×ÙÐÏÌÎÅÎ relative_filename"
+
+#: ../Thuban/Model/classgen.py:338
+msgid "invalid index"
+msgstr "ÎÅÐÒÁ×ÉÌØÎÙÊ ÉÎÄÅËÓ"
+
+#: ../Thuban/Model/classification.py:309 ../Thuban/UI/classifier.py:758
+msgid "None"
+msgstr "îÅÔ"
+
+#: ../Thuban/Model/classification.py:325
+msgid "Line Color"
+msgstr "ã×ÅÔ ÌÉÎÉÉ"
+
+#: ../Thuban/Model/classification.py:327
+#, python-format
+msgid "Line Width: %s"
+msgstr "ûÉÒÉÎÁ ÌÉÎÉÉ: %s"
+
+#: ../Thuban/Model/classification.py:333
+#, fuzzy, python-format
+msgid "Size: %s"
+msgstr "ðÏÌÅ: %s"
+
+#: ../Thuban/Model/classification.py:336
+msgid "Fill"
+msgstr "úÁËÒÁÓÉÔØ"
+
+#: ../Thuban/Model/classification.py:342 ../Thuban/UI/classifier.py:841
+msgid "Classification"
+msgstr "ëÌÁÓÓÉÆÉËÁÃÉÑ"
+
+#: ../Thuban/Model/classification.py:436
+msgid "lineWidth < 1"
+msgstr "lineWidth < 1"
+
+#: ../Thuban/Model/classification.py:451
+msgid "size < 1"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:656 ../Thuban/UI/classifier.py:528
+msgid "DEFAULT"
+msgstr "ðÏ ÕÍÏÌ."
+
+#: ../Thuban/Model/data.py:316
+msgid "Table not compatible with shapestore."
+msgstr "ôÁÂÌÉÃÁ ÎÅÓÏ×ÍÅÓÔÉÍÁ Ó shapestore"
+
+#: ../Thuban/Model/extension.py:90
+#, python-format
+msgid "Extension: %s"
+msgstr "äÏÐÏÌÎÅÎÉÅ: %s"
+
+#: ../Thuban/Model/label.py:91
+#, fuzzy, python-format
+msgid "Number of labels: %d"
+msgstr "þÉÓÌÏ ËÌÁÓÓÏ×:"
+
+#: ../Thuban/Model/label.py:92
+#, fuzzy, python-format
+msgid "Label Layer: %s"
+msgstr "ôÁÂÌÉÃÁ: "
+
+#: ../Thuban/Model/layer.py:298 ../Thuban/Model/layer.py:566
+#: ../Thuban/Model/session.py:432
+#, python-format
+msgid "Filename: %s"
+msgstr "æÁÊÌ: %s"
+
+#: ../Thuban/Model/layer.py:301 ../Thuban/Model/layer.py:569
+msgid "Shown"
+msgstr "ðÏËÁÚÁÎ"
+
+#: ../Thuban/Model/layer.py:303 ../Thuban/Model/layer.py:571
+msgid "Hidden"
+msgstr "óÐÒÑÔÁÎ"
+
+#: ../Thuban/Model/layer.py:304
+#, python-format
+msgid "Shapes: %d"
+msgstr "Shapes: %d"
+
+#: ../Thuban/Model/layer.py:308 ../Thuban/Model/layer.py:575
+#: ../Thuban/Model/map.py:287 ../Thuban/UI/rasterlayerproperties.py:51
+#, python-format
+msgid "Extent (lat-lon): (%g, %g, %g, %g)"
+msgstr "òÁÚÍÁÈ (ÛÉÒ.-ÄÏÌÇ.): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/layer.py:310 ../Thuban/Model/layer.py:577
+msgid "Extent (lat-lon):"
+msgstr "òÁÚÍÁÈ (ÛÉÒ.-ÄÏÌÇ.):"
+
+#: ../Thuban/Model/layer.py:311
+#, python-format
+msgid "Shapetype: %s"
+msgstr "Shapetype: %s"
+
+#: ../Thuban/Model/layer.py:314 ../Thuban/Model/layer.py:580
+#: ../Thuban/Model/map.py:292
+msgid "Projection"
+msgstr "ðÒÏÅËÃÉÑ"
+
+#: ../Thuban/Model/layer.py:319 ../Thuban/Model/layer.py:583
+#, python-format
+msgid "Layer '%s'"
+msgstr "óÌÏÊ '%s'"
+
+#: ../Thuban/Model/load.py:78
+#, python-format
+msgid "Invalid hexadecimal color specification %s"
+msgstr "îÅ×ÅÒÎÁÑ ÛÅÓÔÎÁÄÃÁÔÅÒÉÞÎÁÑ ÓÐÅÃÉÆÉËÁÃÉÑ Ã×ÅÔÁ %s"
+
+#: ../Thuban/Model/load.py:81
+#, python-format
+msgid "Invalid color specification %s"
+msgstr "îÅ×ÅÒÎÁÑ ÓÐÅÃÉÆÉËÁÃÉÑ Ã×ÅÔÁ %s"
+
+#: ../Thuban/Model/load.py:544
+msgid "xml field type differs from database!"
+msgstr "ÔÉÐ ÐÏÌÑ xml ÏÔÌÉÞÁÅÔÓÑ ÏÔ âä! "
+
+#: ../Thuban/Model/load.py:609
+msgid "Classification range is not a number!"
+msgstr "äÉÁÐÁÚÏÎ ËÌÁÓÓÉÆÉËÁÃÉÉ ÎÅ Ñ×ÌÑÅÔÓÑ ÞÉÓÌÏÍ!"
+
+#: ../Thuban/Model/map.py:53
+msgid "Labels"
+msgstr "íÅÔËÉ"
+
+#: ../Thuban/Model/map.py:290
+#, python-format
+msgid "Extent (projected): (%g, %g, %g, %g)"
+msgstr "òÁÚÍÁÈ (× ÐÒÏÅËÃÉÉ): (%g, %g, %g, %g)"
+
+#: ../Thuban/Model/map.py:301
+#, python-format
+msgid "Map: %s"
+msgstr "ëÁÒÔÁ: %s"
+
+#: ../Thuban/Model/proj.py:84 ../Thuban/Model/resource.py:179
+msgid "Unknown"
+msgstr "îÅÉÚ×ÅÓÔÎÁÑ"
+
+#: ../Thuban/Model/resource.py:46
+#, python-format
+msgid ""
+"No GDAL support because module '%s' cannot be imported. Python exception: '%"
+"s'"
+msgstr ""
+"îÅÔ ÐÏÄÄÅÒÖËÉ GDAL, Ô.Ë. ÍÏÄÕÌØ '%s' ÎÅÌØÚÑ ÉÍÐÏÒÔÉÒÏ×ÁÔØ. ïÛÉÂËÁ Python: '%"
+"s'"
+
+#: ../Thuban/Model/resource.py:135 ../Thuban/Model/resource.py:155
+#, python-format
+msgid "Could not read \"%s\": %s"
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ '%s' : %s"
+
+#: ../Thuban/Model/resource.py:187
+#, python-format
+msgid "Error in projection \"%s\": %s"
+msgstr "ïÛÉÂËÁ ÐÒÏÅËÃÉÉ '%s': %s"
+
+#: ../Thuban/Model/save.py:352
+msgid "Unsupported group type in classification"
+msgstr "ôÉÐ ÇÒÕÐÐÙ ÏÔÓÕÔÓÔ×ÕÅÔ × ËÌÁÓÓÉÆÉËÁÃÉÉ"
+
+#: ../Thuban/Model/session.py:430
+msgid "Filename:"
+msgstr "æÁÊÌ:"
+
+#: ../Thuban/Model/session.py:435
+msgid "Modified"
+msgstr "âÙÌ ÉÚÍÅÎÅÎ"
+
+#: ../Thuban/Model/session.py:437
+msgid "Unmodified"
+msgstr "îÅ ÉÚÍÅÎÑÌÓÑ"
+
+#: ../Thuban/Model/session.py:442
+#, python-format
+msgid "Session: %s"
+msgstr "óÅÓÓÉÑ: %s"
+
+#: ../Thuban/Model/session.py:448
+msgid "unnamed session"
+msgstr "ÓÅÓÓÉÑ ÂÅÚ ÎÁÚ×."
+
+#: ../Thuban/Model/session.py:450
+msgid "unnamed map"
+msgstr "ËÁÒÔÁ ÂÅÚ ÎÁÚ×."
+
+#: ../Thuban/UI/about.py:28
+msgid "About Thuban"
+msgstr "ï ÐÒÏÇÒÁÍÍÅ Thuban"
+
+#: ../Thuban/UI/about.py:47
+msgid "French"
+msgstr "æÒÁÎÃÕÚÓËÉÊ"
+
+#: ../Thuban/UI/about.py:48
+msgid "German"
+msgstr "îÅÍÅÃËÉÊ"
+
+#: ../Thuban/UI/about.py:50
+msgid "Hungarian"
+msgstr ""
+
+#: ../Thuban/UI/about.py:51
+msgid "Italian"
+msgstr "éÔÁÌØÑÎÓËÉÊ"
+
+#: ../Thuban/UI/about.py:52
+msgid "Portuguese (Brazilian)"
+msgstr ""
+
+#: ../Thuban/UI/about.py:53
+msgid "Russian"
+msgstr "òÕÓÓËÉÊ"
+
+#: ../Thuban/UI/about.py:54
+msgid "Spanish"
+msgstr "éÓÐÁÎÓËÉÊ"
+
+#: ../Thuban/UI/about.py:63 ../Thuban/UI/about.py:65 ../Thuban/UI/about.py:67
+msgid "- not available"
+msgstr "- ÎÅÔ"
+
+#: ../Thuban/UI/about.py:72
+msgid "Currently using:\n"
+msgstr "éÓÐÏÌØÚÕÅÔÓÑ:\n"
+
+#: ../Thuban/UI/about.py:78
+#, python-format
+msgid "\tInternal encoding: %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:84
+msgid "Compiled for:\n"
+msgstr "óËÏÍÐÉÌÉÒÏ×ÁÎ ÎÁ:\n"
+
+#: ../Thuban/UI/about.py:90
+#, fuzzy
+msgid "Extensions:\n"
+msgstr "äÏÐÏÌÎÅÎÉÅ: %s"
+
+#: ../Thuban/UI/about.py:95 ../Thuban/UI/about.py:144
+msgid "\tNone registered.\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:98
+msgid "Maintainers:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:103
+msgid "Lead Developer:\n"
+msgstr "çÌÁ×ÎÙÊ ÒÁÚÒÁÂÏÔÞÉË:\n"
+
+#: ../Thuban/UI/about.py:106
+msgid "Developers:\n"
+msgstr "òÁÚÒÁÂÏÔÞÉËÉ:\n"
+
+#: ../Thuban/UI/about.py:111
+msgid "Translators:\n"
+msgstr "ðÅÒÅ×ÏÄ:\n"
+
+#: ../Thuban/UI/about.py:116
+msgid "Other Contributors:\n"
+msgstr "äÏÐÏÌÎÅÎÉÑ:\n"
+
+#: ../Thuban/UI/about.py:122
+#, fuzzy
+msgid ""
+"Questions and comments can be sent to the following addresses:\n"
+"\tGeneral list (public):\n"
+"\t\t<thuban-list at intevation.de>\n"
+"\tDevelopers list (public):\n"
+"\t\t<thuban-devel at intevation.de>\n"
+"\tThuban team at Intevation:\n"
+"\t\t<thuban at intevation.de>\n"
+msgstr ""
+"÷ÏÐÒÏÓÙ É ËÏÍÍÅÎÔÁÒÉÉ ÐÒÏÓØÂÁ ÐÒÉÓÙÌÁÔØ ÐÏ ÓÌÅÄÕÀÛÉÍ ÁÄÒÅÓÁÍ:\n"
+"\tòÁÚÒÁÂÏÔÞÉË Thuban:\n"
+"\t\t<thuban at intevation.de>\n"
+"\tMail List Thuban:\n"
+"\t\t<thuban-list at intevation.de>"
+
+#: ../Thuban/UI/about.py:130
+msgid ""
+"Details on the registered extensions:\n"
+"\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:135
+#, python-format
+msgid "Copyright %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:136
+msgid "Authors:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:149
+msgid ""
+"Thuban is a program for exploring geographic data.\n"
+"\n"
+msgstr ""
+"Thuban: ðÒÏÇÒÁÍÍÁ ÄÌÑ ÒÁÂÏÔÙ Ó ÇÅÏÇÒÁÆÉÞÅÓËÉÍÉ ÄÁÎÎÙÍÉ. \n"
+"\n"
+
+#: ../Thuban/UI/about.py:151
+msgid "Thuban is licensed under the GNU GPL"
+msgstr "Thuban ÉÍÅÅÔ ÌÉÃÅÎÚÉÀ GNU GPL"
+
+#: ../Thuban/UI/about.py:160 ../Thuban/UI/classgen.py:91
+#: ../Thuban/UI/dbdialog.py:276 ../Thuban/UI/dock.py:371
+#: ../Thuban/UI/join.py:66 ../Thuban/UI/layerproperties.py:82
+#: ../Thuban/UI/projdialog.py:209 ../Thuban/UI/tableview.py:388
+msgid "Close"
+msgstr "úÁËÒÙÔØ"
+
+#: ../Thuban/UI/altpathdialog.py:24
+#, fuzzy, python-format
+msgid "Select an alternative data file for %s"
+msgstr "÷ÙÂÒÁÔØ ÏÄÉÎ ÉÌÉ ÎÅÓËÏÌØËÏ ÆÁÊÌÏ× Ó ÄÁÎÎÙÍÉ"
+
+#: ../Thuban/UI/altpathdialog.py:31 ../Thuban/UI/mainwindow.py:563
+msgid "Shapefiles (*.shp)"
+msgstr "Shapefiles (*.shp)"
+
+#: ../Thuban/UI/altpathdialog.py:32 ../Thuban/UI/mainwindow.py:564
+#: ../Thuban/UI/mainwindow.py:852
+msgid "All Files (*.*)"
+msgstr "÷ÓÅ ÆÁÊÌÙ (*.*)"
+
+#: ../Thuban/UI/altpathdialog.py:47
+#, python-format
+msgid ""
+"Found the following as an alternative for %s.\n"
+"%s\n"
+"\n"
+" Please confirm with Yes or select alternative with No."
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:49
+msgid "Alternative Path"
+msgstr ""
+
+#: ../Thuban/UI/application.py:110 ../Thuban/UI/application.py:122
+msgid "Cannot import the thubanstart module\n"
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÉÍÐÏÒÔÉÒÏ×ÁÔØ ÍÏÄÕÌØ thubanstart\n"
+
+#: ../Thuban/UI/application.py:115
+msgid "No thubanstart module available\n"
+msgstr "íÏÄÕÌØ thubanstart ÏÔÓÕÔÓÔ×ÕÅÔ\n"
+
+#: ../Thuban/UI/application.py:126
+msgid "No ~/.thuban directory\n"
+msgstr "îÅÔ ÄÉÒÅËÔÏÒÉÉ ~/.thuban\n"
+
+#: ../Thuban/UI/application.py:166
+msgid ""
+"This is the wxPython-based Graphical User Interface for exploring geographic "
+"data"
+msgstr ""
+"çÒÁÆÉÞÅÓËÉÊ ÉÎÔÅÒÆÅÊÓ ÐÏÌØÚÏ×ÁÔÅÌÑ ÎÁ ÏÓÎÏ×Å wxPython ÄÌÑ ÒÁÂÏÔÙ Ó "
+"ÇÅÏÇÒÁÆÉÞÅÓËÉÍÉ ÄÁÎÎÙÍÉ "
+
+#: ../Thuban/UI/application.py:254
+msgid ""
+"The current session contains Image layers,\n"
+"but the GDAL library is not available to draw them."
+msgstr ""
+"äÁÎÎÁÑ ÓÅÓÓÉÑ ÓÏÄÅÒÖÉÔ ÇÒÁÆÉÞÅÓËÉÊ ÆÁÊÌ,\n"
+"ÎÏ ÎÅÔ ÎÅÏÂÈÏÄÉÍÏÊ ÂÉÂÌÉÏÔÅËÉ GDAL."
+
+#: ../Thuban/UI/application.py:259
+msgid "Library not available"
+msgstr "âÉÂÌÉÏÔÅËÁ ÏÔÓÕÔÓÔ×ÕÅÔ"
+
+#: ../Thuban/UI/application.py:268 ../Thuban/UI/mainwindow.py:476
+msgid "DB Connection Parameters"
+msgstr "ðÁÒÁÍÅÔÒÙ ÓÏÅÄÉÎÅÎÉÑ Ó âä"
+
+#: ../Thuban/UI/application.py:364
+#, python-format
+msgid ""
+"An unhandled exception occurred:\n"
+"%s\n"
+"(please report to http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+msgstr ""
+"ðÒÏÉÚÏÛÌÁ ÏÛÉÂËÁ × ÐÒÏÇÒÁÍÍÅ:\n"
+"%s\n"
+"(ÐÏÖÁÌÕÊÓÔÁ, ÓÏÏÂÝÉÔÅ ÎÁ http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/classgen.py:43
+msgid "Uniform Distribution"
+msgstr "ïÄÎÏÒÏÄÎÏÅ ÒÁÓÐÒÅÄÅÌÅÎÉÅ"
+
+#: ../Thuban/UI/classgen.py:44
+msgid "Unique Values"
+msgstr "õÎÉËÁÌØÎÙÅ ×ÅÌÉÞÉÎÙ"
+
+#: ../Thuban/UI/classgen.py:45
+msgid "Quantiles from Table"
+msgstr "ë×ÁÎÔÉÌÉ ÉÚ ÔÁÂÌÉÃÙ"
+
+#: ../Thuban/UI/classgen.py:47
+msgid "Custom Ramp"
+msgstr "ã×ÅÔÏ×ÁÑ ÇÁÍÍÁ"
+
+#: ../Thuban/UI/classgen.py:48
+msgid "Grey Ramp"
+msgstr "óÅÒÁÑ ÇÁÍÍÁ"
+
+#: ../Thuban/UI/classgen.py:49
+msgid "Red Ramp"
+msgstr "ëÒÁÓÎÁÑ ÇÁÍÍÁ"
+
+#: ../Thuban/UI/classgen.py:50
+msgid "Green Ramp"
+msgstr "úÅÌÅÎÁÑ ÇÁÍÍÁ"
+
+#: ../Thuban/UI/classgen.py:51
+msgid "Blue Ramp"
+msgstr "çÏÌÕÂÁÑ ÇÁÍÍÁ"
+
+#: ../Thuban/UI/classgen.py:52
+msgid "Green-to-Red Ramp"
+msgstr "úÅÌÅÎÏ-ËÒÁÓÎÁÑ ÇÁÍÍÁ"
+
+#: ../Thuban/UI/classgen.py:53
+msgid "Hot-to-Cold Ramp"
+msgstr "çÏÒÑÞÁÑ/èÏÌÏÄÎÁÑ ÇÁÍÍÁ"
+
+#: ../Thuban/UI/classgen.py:69
+msgid "Generate Classification"
+msgstr "ëÌÁÓÓÉÆÉËÁÃÉÑ"
+
+#: ../Thuban/UI/classgen.py:90
+msgid "Generate"
+msgstr "óÇÅÎÅÒÉÒÏ×ÁÔØ"
+
+#: ../Thuban/UI/classgen.py:119
+#, python-format
+msgid "Field: %s"
+msgstr "ðÏÌÅ: %s"
+
+#: ../Thuban/UI/classgen.py:123 ../Thuban/UI/classifier.py:976
+#, python-format
+msgid "Data Type: %s"
+msgstr "ôÉÐ ÄÁÎÎÙÈ: %s"
+
+#: ../Thuban/UI/classgen.py:127
+msgid "Generate:"
+msgstr "çÅÎÅÒÉÒÏ×ÁÔØ:"
+
+#: ../Thuban/UI/classgen.py:137
+msgid "Color Scheme:"
+msgstr "ã×ÅÔÏ×ÁÑ ÓÈÅÍÁ:"
+
+#: ../Thuban/UI/classgen.py:161
+msgid "Fix Border Color"
+msgstr "ã×ÅÔ ÌÉÎÉÉ"
+
+#: ../Thuban/UI/classgen.py:168 ../Thuban/UI/classgen.py:936
+#: ../Thuban/UI/classgen.py:967
+msgid "Change"
+msgstr "éÚÍÅÎÉÔØ"
+
+#: ../Thuban/UI/classgen.py:274
+msgid ""
+"Based on the data from the table and the input\n"
+"values, the exact quantiles could not be generated.\n"
+"\n"
+"Accept a close estimate?"
+msgstr ""
+"îÅ×ÏÚÍÏÖÎÏ ÐÏÄÏÂÒÁÔØ ÔÏÞÎÙÅ Ë×ÁÎÔÉÌÉ,\n"
+"ÏÓÎÏ×Ù×ÁÑÓØ ÎÁ ××ÅÄÅÎÎÙÈ ÄÁÎÎÙÈ É ÄÁÎÎÙÈ ÉÚ ÔÁÂÌÉÃÙ.\n"
+"\n"
+"ðÒÉÎÑÔØ Ó ÄÏÐÕÓËÏÍ ÐÏÇÒÅÛÎÏÓÔÉ?"
+
+#: ../Thuban/UI/classgen.py:277
+msgid "Problem with Quantiles"
+msgstr "ðÒÏÂÌÅÍÁ Ó Ë×ÁÎÔÉÌÑÍÉ"
+
+#: ../Thuban/UI/classgen.py:370
+msgid "Min:"
+msgstr "íÉÎ.:"
+
+#: ../Thuban/UI/classgen.py:375
+msgid "Max:"
+msgstr "íÁËÓ.:"
+
+#: ../Thuban/UI/classgen.py:380 ../Thuban/UI/classgen.py:633
+msgid "Retrieve From Table"
+msgstr "÷ÚÑÔØ ÉÚ ÔÁÂÌÉÃÙ"
+
+#: ../Thuban/UI/classgen.py:390
+msgid "Number of Groups:"
+msgstr "þÉÓÌÏ ÇÒÕÐÐ:"
+
+#: ../Thuban/UI/classgen.py:397
+msgid "Stepping:"
+msgstr "ûÁÇ:"
+
+#: ../Thuban/UI/classgen.py:647
+#, fuzzy
+msgid "Available"
+msgstr "- ÎÅÔ"
+
+#: ../Thuban/UI/classgen.py:652 ../Thuban/UI/classgen.py:692
+msgid "Sort"
+msgstr "óÏÒÔÉÒÏ×ÁÔØ"
+
+#: ../Thuban/UI/classgen.py:655 ../Thuban/UI/classgen.py:695
+msgid "Reverse"
+msgstr "ïÂÒÁÔÎÏ"
+
+#: ../Thuban/UI/classgen.py:687
+#, fuzzy
+msgid "Use"
+msgstr "ðÏÌØÚÏ×ÁÔÅÌØ:"
+
+#: ../Thuban/UI/classgen.py:832
+msgid "Retrieve from Table"
+msgstr "÷ÚÑÔØ ÉÚ ÔÁÂÌÉÃÙ"
+
+#: ../Thuban/UI/classgen.py:840
+msgid "Apply to Range"
+msgstr "ðÒÉÍÅÎÉÔØ × ÄÉÁÐÁÚÏÎÅ"
+
+#: ../Thuban/UI/classgen.py:847
+msgid "Number of Classes:"
+msgstr "þÉÓÌÏ ËÌÁÓÓÏ×:"
+
+#: ../Thuban/UI/classgen.py:930
+msgid "Start:"
+msgstr "îÁÞÁÔØ:"
+
+#: ../Thuban/UI/classgen.py:961
+msgid "End:"
+msgstr "úÁËÏÎÞÉÔØ:"
+
+#: ../Thuban/UI/classifier.py:164
+msgid "The Default group cannot be removed."
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:309
+#: ../Thuban/UI/classifier.py:467
+msgid "Pattern"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:306
+#: ../Thuban/UI/classifier.py:466
+msgid "Singleton"
+msgstr "ûÁÇ"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Visible"
+msgstr "÷ÉÚÕÁÌØÎÏ"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Symbol"
+msgstr "óÉÍ×ÏÌ"
+
+#: ../Thuban/UI/classifier.py:317 ../Thuban/UI/controls.py:33
+#: ../Thuban/UI/controls.py:177
+msgid "Value"
+msgstr "÷ÅÌÉÞÉÎÁ"
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Label"
+msgstr "íÅÔËÁ"
+
+#: ../Thuban/UI/classifier.py:462 ../Thuban/UI/classifier.py:465
+msgid "Default"
+msgstr "ðÏ ÕÍÏÌÞÁÎÉÀ"
+
+#: ../Thuban/UI/classifier.py:468
+msgid "Range"
+msgstr "äÉÁÐÁÚÏÎ"
+
+#: ../Thuban/UI/classifier.py:469
+msgid "Map"
+msgstr "ëÁÒÔÁ"
+
+#: ../Thuban/UI/classifier.py:759
+msgid "Text"
+msgstr "ôÅËÓÔ"
+
+#: ../Thuban/UI/classifier.py:760
+msgid "Integer"
+msgstr "ãÅÌÏÅ"
+
+#: ../Thuban/UI/classifier.py:761
+msgid "Decimal"
+msgstr "äÅÓÑÔÉÞÎÏÅ"
+
+#: ../Thuban/UI/classifier.py:820
+msgid "Generate Class"
+msgstr "çÅÎÅÒÉÒÏ×ÁÔØ ËÌÁÓÓ"
+
+#: ../Thuban/UI/classifier.py:822 ../Thuban/UI/dbdialog.py:274
+msgid "Add"
+msgstr "äÏÂÁ×ÉÔØ"
+
+#: ../Thuban/UI/classifier.py:824
+msgid "Move Up"
+msgstr "ðÏÄÎÑÔØ"
+
+#: ../Thuban/UI/classifier.py:826
+msgid "Move Down"
+msgstr "ïÐÕÓÔÉÔØ"
+
+#: ../Thuban/UI/classifier.py:828
+msgid "Edit Symbol"
+msgstr "òÅÄÁËÔÉÒÏ×ÁÔØ ÓÉÍ×ÏÌ"
+
+#: ../Thuban/UI/classifier.py:830 ../Thuban/UI/dbdialog.py:275
+#: ../Thuban/UI/projdialog.py:117
+msgid "Remove"
+msgstr "õÂÒÁÔØ"
+
+#: ../Thuban/UI/classifier.py:845
+msgid "Field: "
+msgstr "óÔÏÌÂÅÃ: "
+
+#: ../Thuban/UI/classifier.py:1000 ../Thuban/UI/layerproperties.py:160
+msgid "Layer Properties"
+msgstr "ó×ÏÊÓÔ×Á ÓÌÏÑ"
+
+#: ../Thuban/UI/classifier.py:1167
+msgid "Select Properties"
+msgstr "÷ÙÂÒÁÔØ Ó×ÏÊÓÔ×Á"
+
+#: ../Thuban/UI/classifier.py:1178
+msgid "Preview:"
+msgstr "ðÒÏÓÍÏÔÒ:"
+
+#: ../Thuban/UI/classifier.py:1195
+msgid "Change Line Color"
+msgstr "éÚÍÅÎÉÔØ Ã×ÅÔ ÌÉÎÉÉ"
+
+#: ../Thuban/UI/classifier.py:1201 ../Thuban/UI/classifier.py:1216
+msgid "Transparent"
+msgstr "ðÒÏÚÒÁÞÎÁÑ"
+
+#: ../Thuban/UI/classifier.py:1212
+msgid "Change Fill Color"
+msgstr "éÚÍÅÎÉÔØ Ã×ÅÔ ÚÁËÒÁÓËÉ"
+
+#: ../Thuban/UI/classifier.py:1225
+msgid "Line Width: "
+msgstr "ûÉÒÉÎÁ ÌÉÎÉÉ: "
+
+#: ../Thuban/UI/classifier.py:1242
+#, fuzzy
+msgid "Size: "
+msgstr "îÁÚ×ÁÎÉÅ:"
+
+#: ../Thuban/UI/classifier.py:1262 ../Thuban/UI/colordialog.py:52
+#: ../Thuban/UI/dbdialog.py:107 ../Thuban/UI/dbdialog.py:221
+#: ../Thuban/UI/labeldialog.py:41 ../Thuban/UI/layerproperties.py:81
+#: ../Thuban/UI/projdialog.py:205
+msgid "OK"
+msgstr "OK"
+
+#: ../Thuban/UI/classifier.py:1264 ../Thuban/UI/colordialog.py:53
+#: ../Thuban/UI/dbdialog.py:110 ../Thuban/UI/dbdialog.py:223
+#: ../Thuban/UI/labeldialog.py:42 ../Thuban/UI/projdialog.py:1033
+msgid "Cancel"
+msgstr "ïÔÍÅÎÉÔØ"
+
+#: ../Thuban/UI/colordialog.py:39
+#, fuzzy
+msgid "Select Color"
+msgstr "÷ÙÂÏÒËÁ"
+
+#: ../Thuban/UI/controls.py:31
+msgid "Field"
+msgstr "óÔÏÌÂÅÃ"
+
+#: ../Thuban/UI/dbdialog.py:41
+msgid "Choose layer from database"
+msgstr "÷ÙÂÒÁÔØ ÓÌÏÊ ÉÚ ÂÁÚÙ ÄÁÎÎÙÈ"
+
+#: ../Thuban/UI/dbdialog.py:59
+msgid "Databases"
+msgstr "âÁÚÙ ÄÁÎÎÙÈ"
+
+#: ../Thuban/UI/dbdialog.py:74
+msgid "Retrieve"
+msgstr "ðÏÌÕÞÉÔØ"
+
+#: ../Thuban/UI/dbdialog.py:82
+msgid "Tables"
+msgstr "&ôÁÂÌÉÃÙ"
+
+#: ../Thuban/UI/dbdialog.py:92
+msgid "ID Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:98
+msgid "Geometry Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:187
+msgid "Hostname:"
+msgstr "éÍÑ ÈÏÓÔÁ:"
+
+#: ../Thuban/UI/dbdialog.py:191
+msgid "Port:"
+msgstr "ðÏÒÔ:"
+
+#: ../Thuban/UI/dbdialog.py:198
+msgid "Database Name:"
+msgstr "îÁÚ×ÁÎÉÅ âä:"
+
+#: ../Thuban/UI/dbdialog.py:206
+msgid "User:"
+msgstr "ðÏÌØÚÏ×ÁÔÅÌØ:"
+
+#: ../Thuban/UI/dbdialog.py:211
+msgid "Password:"
+msgstr "ðÁÒÏÌØ:"
+
+#: ../Thuban/UI/dbdialog.py:286
+msgid "Database Management"
+msgstr "áÄÍÉÎÉÓÔÒÉÒÏ×ÁÎÉÅ âä"
+
+#: ../Thuban/UI/dbdialog.py:361 ../Thuban/UI/dbdialog.py:366
+msgid "Add Database"
+msgstr "äÏÂÁ×ÉÔØ âä"
+
+#: ../Thuban/UI/dbdialog.py:367
+#, python-format
+msgid "Connection '%s' already exists"
+msgstr "óÏÅÄÉÎÅÎÉÅ Ó '%s' ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#: ../Thuban/UI/dbdialog.py:388
+msgid "Remove Database Connection"
+msgstr "úÁËÒÙÔØ ÓÏÅÄÉÎÅÎÉÅ Ó âä"
+
+#: ../Thuban/UI/dbdialog.py:389
+#, python-format
+msgid ""
+"The connection %s\n"
+"is still in use"
+msgstr ""
+"óÏÅÄÉÎÅÎÉÅ %s\n"
+"ÅÝÅ ÉÓÐÏÌØÚÕÅÔÓÑ"
+
+#: ../Thuban/UI/dock.py:190
+msgid "Undock"
+msgstr "ïÔËÒÅÐÉÔØ"
+
+#: ../Thuban/UI/dock.py:218
+msgid "Dock"
+msgstr "ðÒÉËÒÅÐÉÔØ"
+
+#: ../Thuban/UI/exceptiondialog.py:23 ../Thuban/UI/exceptiondialog.py:61
+msgid "Thuban: Internal Error"
+msgstr "Thuban: ×ÎÕÔÒÅÎÎÑÑ ÏÛÉÂËÁ"
+
+#: ../Thuban/UI/exceptiondialog.py:43
+msgid "Proceed"
+msgstr "ðÒÏÄÏÌÖÉÔØ"
+
+#: ../Thuban/UI/exceptiondialog.py:44
+msgid "Exit Thuban now"
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:72
+msgid "Initialization not yet requested."
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:88
+msgid "Initialization successful."
+msgstr ""
+
+#: ../Thuban/UI/identifyview.py:44
+msgid "Identify Shape"
+msgstr "éÎÆÏÒÍÁÃÉÑ Ï ÏÂßÅËÔÅ"
+
+#: ../Thuban/UI/identifyview.py:56
+msgid "Close Window"
+msgstr "úÁËÒÙÔØ ÏËÎÏ"
+
+#: ../Thuban/UI/identifyview.py:57
+msgid "Stop Identify Mode"
+msgstr "îÅ ÐÒÏÉÚ×ÏÄÉÔØ ÚÁÐÒÏÓ"
+
+#: ../Thuban/UI/join.py:64
+msgid "Join"
+msgstr "ðÒÉÓÏÅÄÉÎÉÔØ"
+
+#: ../Thuban/UI/join.py:71 ../Thuban/UI/join.py:72
+#, fuzzy
+msgid "Select..."
+msgstr "÷ÙÂÏÒËÁ"
+
+#: ../Thuban/UI/join.py:100 ../Thuban/UI/join.py:108
+msgid "Table:"
+msgstr "ôÁÂÌÉÃÁ:"
+
+#: ../Thuban/UI/join.py:111 ../Thuban/UI/join.py:114
+msgid "Field:"
+msgstr "óÔÏÌÂÅÃ:"
+
+#: ../Thuban/UI/join.py:125
+msgid "Outer Join (preserves left table records)"
+msgstr "÷ÎÅÛÎÑÑ Ó×ÑÚØ ÔÁÂÌÉà (ÓÏÈÒÁÎÑÅÔ ÏÓÔÁ×ÛÉÅÓÑ ÓÔÒÏËÉ)"
+
+#: ../Thuban/UI/join.py:173
+#, python-format
+msgid ""
+"Join failed:\n"
+"  %s"
+msgstr ""
+"óÂÏÊ Ó×ÑÚÉ:\n"
+"  %s"
+
+#: ../Thuban/UI/join.py:174
+msgid "Info"
+msgstr "éÎÆÏ"
+
+#: ../Thuban/UI/join.py:195
+#, python-format
+msgid ""
+"The joined table has %(joined)d rows but it must have %(needed)d rows to be "
+"used with the selected layer"
+msgstr ""
+"ðÒÉÓÏÅÄÉÎÅÎÎÁÑ ÔÁÂÌÉÃÁ ÉÍÅÅÔ %(joined)d ÓÔÒÏË, ÎÏ ÄÏÌÖÎÏ ÂÙÔØ %(needed)d ÄÌÑ "
+"×ÏÚÍÏÖÎÏÓÔÉ ÉÓÐÏÌØÚÏ×ÁÎÉÑ ×ÙÂÒÁÎÎÏÇÏ ÓÌÏÑ"
+
+#: ../Thuban/UI/join.py:200
+msgid "Join Failed"
+msgstr "óÂÏÊ Ó×ÑÚÉ"
+
+#: ../Thuban/UI/join.py:209 ../Thuban/UI/mainwindow.py:915
+#, fuzzy, python-format
+msgid "Table: %s"
+msgstr "ôÁÂÌÉÃÁ: "
+
+#: ../Thuban/UI/labeldialog.py:26
+msgid "Label Values"
+msgstr "úÎÁÞÅÎÉÑ ÍÅÔÏË"
+
+#: ../Thuban/UI/layerproperties.py:54
+msgid "Title: "
+msgstr "îÁÚ×ÁÎÉÅ:"
+
+#: ../Thuban/UI/layerproperties.py:65
+#, fuzzy, python-format
+msgid "Layer Type: %s"
+msgstr "ôÁÂÌÉÃÁ ÓÌÏÑ: %s"
+
+#: ../Thuban/UI/layerproperties.py:71
+#, fuzzy
+msgid "Projection: None"
+msgstr "ðÒÏÅËÃÉÑ:"
+
+#: ../Thuban/UI/layerproperties.py:73
+#, fuzzy, python-format
+msgid "Projection: %s"
+msgstr "ðÒÏÅËÃÉÑ:"
+
+#: ../Thuban/UI/layerproperties.py:79 ../Thuban/UI/projdialog.py:199
+msgid "Try"
+msgstr "ðÒÏÂÁ"
+
+#: ../Thuban/UI/layerproperties.py:80 ../Thuban/UI/projdialog.py:202
+msgid "Revert"
+msgstr "÷ÅÒÎÕÔØ"
+
+#: ../Thuban/UI/legend.py:75
+msgid "Top Layer"
+msgstr "îÁ ÓÁÍÙÊ ×ÅÒÈ"
+
+#: ../Thuban/UI/legend.py:79
+msgid "Raise Layer"
+msgstr "ðÏÄÎÑÔØ ÓÌÏÊ"
+
+#: ../Thuban/UI/legend.py:83
+msgid "Lower Layer"
+msgstr "ïÐÕÓÔÉÔØ ÓÌÏÊ"
+
+#: ../Thuban/UI/legend.py:87
+msgid "Bottom Layer"
+msgstr "÷ ÓÁÍÙÊ ÎÉÚ"
+
+#: ../Thuban/UI/legend.py:91
+msgid "Show Layer"
+msgstr "ðÏËÁÚÁÔØ ÓÌÏÊ"
+
+#: ../Thuban/UI/legend.py:95
+msgid "Hide Layer"
+msgstr "óËÒÙÔØ ÓÌÏÊ"
+
+#: ../Thuban/UI/legend.py:99
+msgid "Edit Layer Properties"
+msgstr "òÅÄÁËÔÉÒÏ×ÁÔØ Ó×ÏÊÓÔ×Á ÓÌÏÑ"
+
+#: ../Thuban/UI/mainwindow.py:264 ../Thuban/UI/mainwindow.py:286
+#, fuzzy, python-format
+msgid "Unknown command %s"
+msgstr "îÅÉÚ×ÅÓÔÎÁÑ ËÏÍÁÎÄÁ %"
+
+#: ../Thuban/UI/mainwindow.py:299
+#, fuzzy, python-format
+msgid "Unknown command ID %d"
+msgstr "îÅÉÚ×ÅÓÔÎÁÑ ID ËÏÍÁÎÄÙ %"
+
+#: ../Thuban/UI/mainwindow.py:338
+#, python-format
+msgid "The Dialog named %s is already open"
+msgstr "äÉÁÌÏÇ %s ÕÖÅ ÏÔËÒÙÔ"
+
+#: ../Thuban/UI/mainwindow.py:396
+#, python-format
+msgid "Select layer '%s' and pick a projection using Layer/Projection..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:449
+msgid "Exit"
+msgstr "÷ÙÊÔÉ"
+
+#: ../Thuban/UI/mainwindow.py:450
+msgid "The session has been modified. Do you want to save it?"
+msgstr "óÅÓÓÉÑ ÂÙÌÁ ÉÚÍÅÎÅÎÁ. óÏÈÒÁÎÉÔØ?"
+
+#: ../Thuban/UI/mainwindow.py:465
+msgid "Open Session"
+msgstr "ïÔËÒÙÔØ"
+
+#: ../Thuban/UI/mainwindow.py:487
+msgid "Save Session As"
+msgstr "óÏÈÒÁÎÉÔØ ËÁË"
+
+#: ../Thuban/UI/mainwindow.py:561
+msgid "Select one or more data files"
+msgstr "÷ÙÂÒÁÔØ ÏÄÉÎ ÉÌÉ ÎÅÓËÏÌØËÏ ÆÁÊÌÏ× Ó ÄÁÎÎÙÍÉ"
+
+#: ../Thuban/UI/mainwindow.py:576
+msgid "Add Layer"
+msgstr "äÏÂÁ×ÉÔØ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:577 ../Thuban/UI/mainwindow.py:602
+#: ../Thuban/UI/mainwindow.py:862
+#, fuzzy, python-format
+msgid "Can't open the file '%s'."
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ '%'"
+
+#: ../Thuban/UI/mainwindow.py:589
+msgid "Select an image file"
+msgstr "÷ÙÂÒÁÔØ ÇÒÁÆÉÞÅÓËÉÊ ÆÁÊÌ"
+
+#: ../Thuban/UI/mainwindow.py:601
+msgid "Add Image Layer"
+msgstr "äÏÂÁ×ÉÔØ ÒÁÓÔÒ"
+
+#: ../Thuban/UI/mainwindow.py:629
+msgid "Add Layer from database"
+msgstr "äÏÂÁ×ÉÔØ ÓÌÏÊ ÉÚ âä"
+
+#: ../Thuban/UI/mainwindow.py:630
+#, fuzzy, python-format
+msgid "Can't open the database table '%s'"
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ âä '%'."
+
+#: ../Thuban/UI/mainwindow.py:719
+#, python-format
+msgid "Copy of `%s'"
+msgstr "ëÏÐÉÑ `%s'"
+
+#: ../Thuban/UI/mainwindow.py:749
+#, python-format
+msgid "Layer Table: %s"
+msgstr "ôÁÂÌÉÃÁ ÓÌÏÑ: %s"
+
+#: ../Thuban/UI/mainwindow.py:764
+#, python-format
+msgid "Map Projection: %s"
+msgstr "ðÒÏÅËÃÉÑ ËÁÒÔÙ: %s"
+
+#: ../Thuban/UI/mainwindow.py:779
+#, python-format
+msgid "Layer Projection: %s"
+msgstr "ðÒÏÅËÃÉÑ ÓÌÏÑ: %s"
+
+#: ../Thuban/UI/mainwindow.py:812
+msgid "Join Layer with Table"
+msgstr "óÏÅÄÉÎÉÔØ ÓÌÏÊ Ó ÔÁÂÌÉÃÅÊ"
+
+#: ../Thuban/UI/mainwindow.py:834 ../Thuban/UI/mainwindow.py:1165
+msgid "Legend"
+msgstr "õÓÌÏ×ÎÙÅ ÏÂÏÚÎÁÞÅÎÉÑ"
+
+#: ../Thuban/UI/mainwindow.py:848 ../Thuban/UI/mainwindow.py:861
+msgid "Open Table"
+msgstr "ïÔËÒÙÔØ ÔÁÂÌÉÃÕ"
+
+#: ../Thuban/UI/mainwindow.py:850
+msgid "DBF Files (*.dbf)"
+msgstr "æÁÊÌÙ DBF (*.dbf) "
+
+#: ../Thuban/UI/mainwindow.py:873
+msgid "Pick the tables to close:"
+msgstr "÷ÙÂÒÁÔØ ÔÁÂÌÉÃÕ:"
+
+#: ../Thuban/UI/mainwindow.py:874
+msgid "Close Table"
+msgstr "úÁËÒÙÔØ ÔÁÂÌÉÃÕ"
+
+#: ../Thuban/UI/mainwindow.py:894
+msgid "Pick the table to show:"
+msgstr "÷ÙÂÒÁÔØ ÔÁÂÌÉÃÕ:"
+
+#: ../Thuban/UI/mainwindow.py:895
+msgid "Show Table"
+msgstr "ðÏËÁÚÁÔØ ÔÁÂÌÉÃÕ"
+
+#: ../Thuban/UI/mainwindow.py:906
+msgid "Join Tables"
+msgstr "ðÒÉÓÏÅÄÉÎÉÔØ ÔÁÂÌÉÃÙ"
+
+#: ../Thuban/UI/mainwindow.py:929
+msgid "Pick the table to rename:"
+msgstr "÷ÙÂÒÁÔØ ÔÁÂÌÉÃÕ:"
+
+#: ../Thuban/UI/mainwindow.py:930 ../Thuban/UI/mainwindow.py:942
+msgid "Rename Table"
+msgstr "ðÅÒÅÉÍÅÎÏ×ÁÔØ ÔÁÂÌÉÃÕ"
+
+#: ../Thuban/UI/mainwindow.py:942
+#, fuzzy
+msgid "Table Title:"
+msgstr "ôÁÂÌÉÃÁ:"
+
+#: ../Thuban/UI/mainwindow.py:991
+#, fuzzy
+msgid "Map Title:"
+msgstr "îÁÚ×ÁÎÉÅ:"
+
+#: ../Thuban/UI/mainwindow.py:991
+#, fuzzy
+msgid "Rename Map"
+msgstr "ðÅÒÅÉÍÅÎÏ×ÁÔØ ËÁÒÔÕ"
+
+#: ../Thuban/UI/mainwindow.py:1004
+#, fuzzy
+msgid "Layer Title:"
+msgstr "ôÁÂÌÉÃÁ ÓÌÏÑ: %s"
+
+#: ../Thuban/UI/mainwindow.py:1004
+#, fuzzy
+msgid "Rename Layer"
+msgstr "&õÂÒÁÔØ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1057
+#, python-format
+msgid "Thuban - %s"
+msgstr "Thuban - %s"
+
+#: ../Thuban/UI/mainwindow.py:1059
+msgid "Thuban"
+msgstr "Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1154
+msgid "&New Session"
+msgstr "&îÏ×ÁÑ ÓÅÓÓÉÑ"
+
+#: ../Thuban/UI/mainwindow.py:1155
+msgid "Start a new session"
+msgstr "îÁÞÁÔØ ÎÏ×ÕÀ ÓÅÓÓÉÀ"
+
+#: ../Thuban/UI/mainwindow.py:1156
+msgid "&Open Session..."
+msgstr "&ïÔËÒÙÔØ..."
+
+#: ../Thuban/UI/mainwindow.py:1157
+msgid "Open a session file"
+msgstr "ïÔËÒÙÔØ ÆÁÊÌ ÓÅÓÓÉÉ"
+
+#: ../Thuban/UI/mainwindow.py:1158
+msgid "&Save Session"
+msgstr "&óÏÈÒÁÎÉÔØ"
+
+#: ../Thuban/UI/mainwindow.py:1159
+msgid "Save this session to the file it was opened from"
+msgstr "óÏÈÒÁÎÉÔØ ÓÅÓÓÉÀ × ÆÁÊÌ"
+
+#: ../Thuban/UI/mainwindow.py:1160
+msgid "Save Session &As..."
+msgstr "óÏÈÒÁÎÉÔØ ËÁË..."
+
+#: ../Thuban/UI/mainwindow.py:1161
+msgid "Save this session to a new file"
+msgstr "óÏÈÒÁÎÉÔØ × ÎÏ×ÙÊ ÆÁÊÌ"
+
+#: ../Thuban/UI/mainwindow.py:1162
+msgid "Session &Tree"
+msgstr "äÅÒÅ×Ï ÓÅÓÓÉÉ"
+
+#: ../Thuban/UI/mainwindow.py:1164
+msgid "Toggle on/off the session tree analysis window"
+msgstr "ðÏËÁÚÁÔØ/õÂÒÁÔØ ÄÅÒÅ×Ï ÓÅÓÓÉÉ"
+
+#: ../Thuban/UI/mainwindow.py:1167
+msgid "Toggle Legend on/off"
+msgstr "ðÏËÁÚÁÔØ/õÂÒÁÔØ ÕÓÌÏ×ÎÙÅ ÏÂÏÚÎÁÞÅÎÉÑ"
+
+#: ../Thuban/UI/mainwindow.py:1168
+msgid "&Database Connections..."
+msgstr "&ó×ÑÚØ Ó âä"
+
+#: ../Thuban/UI/mainwindow.py:1171
+msgid "E&xit"
+msgstr "&÷ÙÊÔÉ"
+
+#: ../Thuban/UI/mainwindow.py:1172
+msgid "Finish working with Thuban"
+msgstr "úÁËÏÎÞÉÔØ ÒÁÂÏÔÕ Ó ÐÒÏÇÒÁÍÍÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1175
+msgid "&About..."
+msgstr "&ï ÐÒÏÇÒÁÍÍÅ..."
+
+#: ../Thuban/UI/mainwindow.py:1176
+msgid "Info about Thuban authors, version and modules"
+msgstr "éÎÆÏÒÍÁÃÉÑ Ï Á×ÔÏÒÁÈ, ×ÅÒÓÉÉ É ÍÏÄÕÌÑÈ Thuban"
+
+#: ../Thuban/UI/mainwindow.py:1180 ../Thuban/UI/mainwindow.py:1228
+msgid "Pro&jection..."
+msgstr "&ðÒÏÅËÃÉÑ..."
+
+#: ../Thuban/UI/mainwindow.py:1181
+msgid "Set or change the map projection"
+msgstr "õÓÔÁÎÏ×ÉÔØ ÉÌÉ ÐÏÍÅÎÑÔØ ÐÒÏÅËÃÉÀ ËÁÒÔÙ"
+
+#: ../Thuban/UI/mainwindow.py:1183
+msgid "&Zoom in"
+msgstr "õ×ÅÌÉÞÉÔØ"
+
+#: ../Thuban/UI/mainwindow.py:1184
+msgid "Switch to map-mode 'zoom-in'"
+msgstr "òÅÖÉÍ Õ×ÅÌÉÞÅÎÉÑ"
+
+#: ../Thuban/UI/mainwindow.py:1186
+msgid "Zoom &out"
+msgstr "õÍÅÎØÛÉÔØ"
+
+#: ../Thuban/UI/mainwindow.py:1187
+msgid "Switch to map-mode 'zoom-out'"
+msgstr "òÅÖÉÍ ÕÍÅÎØÛÅÎÉÑ"
+
+#: ../Thuban/UI/mainwindow.py:1189
+msgid "&Pan"
+msgstr "&ðÅÒÅÎÏÓ"
+
+#: ../Thuban/UI/mainwindow.py:1190
+msgid "Switch to map-mode 'pan'"
+msgstr "òÅÖÉÍ ÐÅÒÅÎÏÓÁ ÐÏ ËÁÒÔÅ"
+
+#: ../Thuban/UI/mainwindow.py:1192
+msgid "&Identify"
+msgstr "úÁÐÒÏÓ"
+
+#: ../Thuban/UI/mainwindow.py:1194
+msgid "Switch to map-mode 'identify'"
+msgstr "òÅÖÉÍ ÚÁÐÒÏÓÏ×"
+
+#: ../Thuban/UI/mainwindow.py:1196
+msgid "&Label"
+msgstr "íÅÔËÉ"
+
+#: ../Thuban/UI/mainwindow.py:1197
+msgid "Add/Remove labels"
+msgstr "äÏÂÁ×ÉÔØ/õÂÒÁÔØ ÍÅÔËÉ"
+
+#: ../Thuban/UI/mainwindow.py:1199
+msgid "&Full extent"
+msgstr "÷ÅÓØ ÒÁÊÏÎ"
+
+#: ../Thuban/UI/mainwindow.py:1200
+msgid "Zoom to the full map extent"
+msgstr "õÓÔÁÎÏ×ÉÔØ ÏËÎÏ ÐÏ ×ÓÅÍÕ ÒÅÇÉÏÎÕ"
+
+#: ../Thuban/UI/mainwindow.py:1202
+msgid "&Full layer extent"
+msgstr "÷ÅÓØ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1203
+msgid "Zoom to the full layer extent"
+msgstr "õÓÔÁÎÏ×ÉÔØ ÏËÎÏ ÐÏ ×ÓÅÍÕ ÓÌÏÀ"
+
+#: ../Thuban/UI/mainwindow.py:1205
+msgid "&Full selection extent"
+msgstr "÷ÓÑ ×ÙÂÏÒËÁ"
+
+#: ../Thuban/UI/mainwindow.py:1207
+msgid "Zoom to the full selection extent"
+msgstr "õÓÔÁÎÏ×ÉÔØ ÏËÎÏ ÐÏ ×ÓÅÊ ×ÙÂÏÒËÅ"
+
+#: ../Thuban/UI/mainwindow.py:1209
+msgid "E&xport"
+msgstr "üËÓÐÏÒÔ"
+
+#: ../Thuban/UI/mainwindow.py:1210
+msgid "Export the map to file"
+msgstr "üËÓÐÏÒÔÉÒÏ×ÁÔØ ËÁÒÔÕ × ÆÁÊÌ"
+
+#: ../Thuban/UI/mainwindow.py:1211
+msgid "Prin&t"
+msgstr "ðÅÞÁÔØ"
+
+#: ../Thuban/UI/mainwindow.py:1212
+msgid "Print the map"
+msgstr "îÁÐÅÞÁÔÁÔØ ËÁÒÔÕ"
+
+#: ../Thuban/UI/mainwindow.py:1213 ../Thuban/UI/mainwindow.py:1299
+msgid "&Rename..."
+msgstr "ðÅÒÅÉÍÅÎÏ×ÁÔØ..."
+
+#: ../Thuban/UI/mainwindow.py:1214
+msgid "Rename the map"
+msgstr "ðÅÒÅÉÍÅÎÏ×ÁÔØ ËÁÒÔÕ"
+
+#: ../Thuban/UI/mainwindow.py:1215
+msgid "&Add Layer..."
+msgstr "&îÏ×ÙÊ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1216
+msgid "Add a new layer to the map"
+msgstr "äÏÂÁ×ÉÔØ ÓÌÏÊ Ë ËÁÒÔÅ"
+
+#: ../Thuban/UI/mainwindow.py:1217
+msgid "&Add Image Layer..."
+msgstr "&äÏÂÁ×ÉÔØ ÒÁÓÔÒ..."
+
+#: ../Thuban/UI/mainwindow.py:1218
+msgid "Add a new image layer to the map"
+msgstr "äÏÂÁ×ÉÔØ ÒÁÓÔÒÏ×ÏÅ ÉÚÏÂÒÁÖÅÎÉÅ × ËÁÒÔÕ"
+
+#: ../Thuban/UI/mainwindow.py:1220
+msgid "Add &Database Layer..."
+msgstr "&äÏÂÁ×ÉÔØ ÓÌÏÊ âä"
+
+#: ../Thuban/UI/mainwindow.py:1221
+msgid "Add a new database layer to active map"
+msgstr "äÏÂÁ×ÉÔØ ÎÏ×ÙÊ ÓÌÏÊ âä"
+
+#: ../Thuban/UI/mainwindow.py:1223
+msgid "&Remove Layer"
+msgstr "&õÂÒÁÔØ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1224
+msgid "Remove selected layer"
+msgstr "õÂÒÁÔØ ×ÙÂÒÁÎÎÙÊ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1230
+msgid "Specify projection for selected layer"
+msgstr "õËÁÚÁÔØ ÐÒÏÅËÃÉÀ ÄÌÑ ×ÙÂÒÁÎÎÏÇÏ ÓÌÏÑ"
+
+#: ../Thuban/UI/mainwindow.py:1231
+msgid "&Duplicate"
+msgstr "&äÏÂÁ×ÉÔØ ËÏÐÉÀ"
+
+#: ../Thuban/UI/mainwindow.py:1232
+msgid "Duplicate selected layer"
+msgstr "óËÏÐÉÒÏ×ÁÔØ ×ÙÂÒÁÎÎÙÊ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1234
+msgid "Re&name ..."
+msgstr "ðÅÒÅÉÍÅÎÏ×ÁÔØ..."
+
+#: ../Thuban/UI/mainwindow.py:1235
+msgid "Rename selected layer"
+msgstr "ðÅÒÅÉÍÅÎÏ×ÁÔØ ×ÙÂÒÁÎÎÙÊ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1237
+msgid "&Raise"
+msgstr "ðÏÄÎÑÔØ"
+
+#: ../Thuban/UI/mainwindow.py:1238
+msgid "Raise selected layer"
+msgstr "ðÏÄÎÑÔØ ×ÙÂÒÁÎÎÙÊ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1240
+msgid "&Lower"
+msgstr "ïÐÕÓÔÉÔØ"
+
+#: ../Thuban/UI/mainwindow.py:1241
+msgid "Lower selected layer"
+msgstr "ïÐÕÓÔÉÔØ ×ÙÂÒÁÎÎÙÊ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1243
+msgid "&Show"
+msgstr "&ðÏËÁÚÁÔØ"
+
+#: ../Thuban/UI/mainwindow.py:1244
+msgid "Make selected layer visible"
+msgstr "ðÏËÁÚÁÔØ ×ÙÂÒÁÎÎÙÊ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1246
+msgid "&Hide"
+msgstr "&óÐÒÑÔÁÔØ"
+
+#: ../Thuban/UI/mainwindow.py:1247
+msgid "Make selected layer unvisible"
+msgstr "îÅ ÐÏËÁÚÙ×ÁÔØ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1249
+msgid "Show Ta&ble"
+msgstr "ðÏËÁÚÁÔØ &ÔÁÂÌÉÃÕ"
+
+#: ../Thuban/UI/mainwindow.py:1250
+msgid "Show the selected layer's table"
+msgstr "ðÏËÁÚÁÔØ ÔÁÂÌÉÃÕ ÄÌÑ ÌÁÎÎÏÇÏ ÓÌÏÑ"
+
+#: ../Thuban/UI/mainwindow.py:1252
+msgid "&Properties..."
+msgstr "&ó×ÏÊÓÔ×Á..."
+
+#: ../Thuban/UI/mainwindow.py:1254
+msgid "Edit the properties of the selected layer"
+msgstr "òÅÄÁËÔÉÒÏ×ÁÔØ Ó×ÏÊÓÔ×Á ÄÁÎÎÏÇÏ ÓÌÏÑ"
+
+#: ../Thuban/UI/mainwindow.py:1255
+msgid "&Join Table..."
+msgstr "&ðÒÉÓÏÅÄÉÎÉÔØ ÔÁÂÌÉÃÕ"
+
+#: ../Thuban/UI/mainwindow.py:1257
+msgid "Join and attach a table to the selected layer"
+msgstr "ðÒÉËÒÅÐÉÔØ ÔÁÂÌÉÃÕ Ë ÄÁÎÎÏÇÏ ÓÌÏÀ"
+
+#: ../Thuban/UI/mainwindow.py:1260
+msgid "&Top"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1261
+#, fuzzy
+msgid "Put selected layer to the top"
+msgstr "óËÏÐÉÒÏ×ÁÔØ ×ÙÂÒÁÎÎÙÊ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1263
+#, fuzzy
+msgid "&Bottom"
+msgstr "÷ ÓÁÍÙÊ ÎÉÚ"
+
+#: ../Thuban/UI/mainwindow.py:1264
+#, fuzzy
+msgid "Put selected layer to the bottom"
+msgstr "óËÏÐÉÒÏ×ÁÔØ ×ÙÂÒÁÎÎÙÊ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1266
+#, fuzzy
+msgid "&Visible"
+msgstr "÷ÉÚÕÁÌØÎÏ"
+
+#: ../Thuban/UI/mainwindow.py:1268
+#, fuzzy
+msgid "Toggle visibility of selected layer"
+msgstr "ðÏÄÎÑÔØ ×ÙÂÒÁÎÎÙÊ ÓÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1285
+msgid "&Unjoin Table..."
+msgstr "ïÔÓÏÅÄÉÎÉÔØ"
+
+#: ../Thuban/UI/mainwindow.py:1287
+msgid "Undo the last join operation"
+msgstr "ïÔÍÅÎÉÔØ ÐÏÓÌÅÄÎÀÀ ÏÐÅÒÁÃÉÀ ÐÒÉÓÏÅÄÉÎÅÎÉÑ ÔÁÂÌÉÃÙ"
+
+#: ../Thuban/UI/mainwindow.py:1294
+msgid "&Open..."
+msgstr "&ïÔËÒÙÔØ"
+
+#: ../Thuban/UI/mainwindow.py:1295
+msgid "Open a DBF-table from a file"
+msgstr "ïÔËÒÙÔØ DBF-ÔÁÂÌÉÃÕ ÉÚ ÆÁÊÌÁ"
+
+#: ../Thuban/UI/mainwindow.py:1296
+msgid "&Close..."
+msgstr "&úÁËÒÙÔØ..."
+
+#: ../Thuban/UI/mainwindow.py:1298
+msgid "Close one or more tables from a list"
+msgstr "úÁËÒÙÔØ ÏÄÎÕ ÉÌÉ ÎÅÓËÏÌØËÏ ÔÁÂÌÉÃ ÉÚ ÓÐÉÓËÁ"
+
+#: ../Thuban/UI/mainwindow.py:1301
+msgid "Rename one or more tables"
+msgstr "ðÅÒÅÉÍÅÎÏ×ÁÔØ ÏÄÎÕ ÉÌÉ ÎÅÓËÏÌØËÏ ÔÁÂÌÉÃ"
+
+#: ../Thuban/UI/mainwindow.py:1302
+msgid "&Show..."
+msgstr "&ðÏËÁÚÁÔØ..."
+
+#: ../Thuban/UI/mainwindow.py:1304
+msgid "Show one or more tables in a dialog"
+msgstr "ðÏËÁÚÁÔØ × ÏËÎÅ ÏÄÎÕ ÉÌÉ ÎÅÓËÏÌØËÏ ÔÁÂÌÉÃ"
+
+#: ../Thuban/UI/mainwindow.py:1305
+msgid "&Join..."
+msgstr "&ðÒÉÓÏÅÄÉÎÉÔØ..."
+
+#: ../Thuban/UI/mainwindow.py:1307
+msgid "Join two tables creating a new one"
+msgstr "óÏÅÄÉÎÉÔØ Ä×Å ÔÁÂÌÉÃÙ × ÏÄÎÕ"
+
+#: ../Thuban/UI/mainwindow.py:1331
+msgid "&File"
+msgstr "&æÁÊÌ"
+
+#: ../Thuban/UI/mainwindow.py:1337
+msgid "&Map"
+msgstr "&ëÁÒÔÁ"
+
+#: ../Thuban/UI/mainwindow.py:1338
+msgid "&Layer"
+msgstr "&óÌÏÊ"
+
+#: ../Thuban/UI/mainwindow.py:1352
+msgid "&Table"
+msgstr "&ôÁÂÌÉÃÁ"
+
+#: ../Thuban/UI/mainwindow.py:1358
+msgid "&Help"
+msgstr "&ðÏÍÏÝØ"
+
+#: ../Thuban/UI/menu.py:90
+#, python-format
+msgid "Submenu %s doesn't exist"
+msgstr "íÅÎÀ %s ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
+
+#: ../Thuban/UI/projdialog.py:62 ../Thuban/UI/projdialog.py:776
+msgid "Transverse Mercator"
+msgstr "Transverse Mercator"
+
+#: ../Thuban/UI/projdialog.py:63 ../Thuban/UI/projdialog.py:842
+msgid "Universal Transverse Mercator"
+msgstr "Universal Transverse Mercator"
+
+#: ../Thuban/UI/projdialog.py:64 ../Thuban/UI/projdialog.py:918
+msgid "Lambert Conic Conformal"
+msgstr "Lambert Conic Conformal"
+
+#: ../Thuban/UI/projdialog.py:65 ../Thuban/UI/projdialog.py:66
+#: ../Thuban/UI/projdialog.py:968
+msgid "Geographic"
+msgstr "Geographic"
+
+#: ../Thuban/UI/projdialog.py:110
+msgid "Import..."
+msgstr "éÍÐÏÒÔ..."
+
+#: ../Thuban/UI/projdialog.py:113
+msgid "Export..."
+msgstr "üËÓÐÏÒÔ..."
+
+#: ../Thuban/UI/projdialog.py:122
+msgid "Show EPSG:"
+msgstr "ðÏËÁÚÁÔØ EPSG:"
+
+#: ../Thuban/UI/projdialog.py:124
+msgid "Normal"
+msgstr "îÏÒÍÁÌØÎÙÊ"
+
+#: ../Thuban/UI/projdialog.py:127
+msgid "Deprecated"
+msgstr "îÅ ÉÓÐÏÌØÚÕÅÔÓÑ"
+
+#: ../Thuban/UI/projdialog.py:138
+msgid "Edit"
+msgstr "òÅÄÁËÔÉÒÏ×ÁÔØ"
+
+#: ../Thuban/UI/projdialog.py:148
+msgid "Name:"
+msgstr "îÁÚ×ÁÎÉÅ:"
+
+#: ../Thuban/UI/projdialog.py:156
+msgid "Projection:"
+msgstr "ðÒÏÅËÃÉÑ:"
+
+#: ../Thuban/UI/projdialog.py:167 ../Thuban/UI/projdialog.py:648
+msgid "<Unknown>"
+msgstr "<îÅÉÚ×ÅÓÔÎÁÑ>"
+
+#: ../Thuban/UI/projdialog.py:183
+msgid "New"
+msgstr "îÏ×ÁÑ"
+
+#: ../Thuban/UI/projdialog.py:186
+msgid "Add to List"
+msgstr "äÏÂÁ×ÉÔØ × ÓÐÉÓÏË"
+
+#: ../Thuban/UI/projdialog.py:190
+msgid "Update"
+msgstr "éÚÍÅÎÉÔØ"
+
+#: ../Thuban/UI/projdialog.py:295
+#, python-format
+msgid ""
+"Warnings when reading \"%s\":\n"
+"\n"
+"%s"
+msgstr ""
+"ðÒÅÄÕÐÒÅÖÄÅÎÉÅ '%s':\n"
+"\n"
+"%s"
+
+#: ../Thuban/UI/projdialog.py:306
+msgid "Import"
+msgstr "éÍÐÏÒÔ"
+
+#: ../Thuban/UI/projdialog.py:319 ../Thuban/UI/projdialog.py:617
+msgid "Warnings"
+msgstr "ðÒÅÄÕÐÒÅÖÄÅÎÉÑ"
+
+#: ../Thuban/UI/projdialog.py:337 ../Thuban/UI/tableview.py:386
+msgid "Export"
+msgstr "üËÓÐÏÒÔ"
+
+#: ../Thuban/UI/projdialog.py:389
+msgid "The following error occured:\n"
+msgstr "ðÒÏÉÚÏÛÌÁ ÓÌÅÄÕÀÝÁÑ ÏÛÉÂËÁ: \n"
+
+#: ../Thuban/UI/projdialog.py:391
+msgid "Error"
+msgstr "ïÛÉÂËÁ"
+
+#: ../Thuban/UI/projdialog.py:460
+msgid "No Projections selected"
+msgstr "ðÒÏÅËÃÉÑ ÎÅ ÕÓÔÁÎÏ×ÌÅÎÁ"
+
+#: ../Thuban/UI/projdialog.py:470
+#, python-format
+msgid "Source of Projection: %s"
+msgstr "éÓÈÏÄÎÁÑ ÐÒÏÅËÃÉÑ: %s"
+
+#: ../Thuban/UI/projdialog.py:502
+msgid "Multiple Projections selected"
+msgstr "÷ÙÂÒÁÎÏ ÍÎÏÇÏ ÐÒÏÅËÃÉÊ"
+
+#: ../Thuban/UI/projdialog.py:649
+msgid "Airy"
+msgstr "Airy"
+
+#: ../Thuban/UI/projdialog.py:650
+msgid "Bessel 1841"
+msgstr "Bessel 1841"
+
+#: ../Thuban/UI/projdialog.py:651
+msgid "Clarke 1866"
+msgstr "Clarke 1866"
+
+#: ../Thuban/UI/projdialog.py:652
+msgid "Clarke 1880"
+msgstr "Clarke 1880"
+
+#: ../Thuban/UI/projdialog.py:653
+msgid "GRS 1980 (IUGG, 1980)"
+msgstr "GRS 1980 (IUGG, 1980)"
+
+#: ../Thuban/UI/projdialog.py:654
+msgid "International 1909 (Hayford)"
+msgstr "International 1909 (Hayford)"
+
+#: ../Thuban/UI/projdialog.py:655
+msgid "WGS 84"
+msgstr "WGS 84"
+
+#: ../Thuban/UI/projdialog.py:667
+msgid "Ellipsoid:"
+msgstr "üÌÌÉÐÓÏÉÄ:"
+
+#: ../Thuban/UI/projdialog.py:716
+msgid ""
+"Thuban does not know the parameters\n"
+"for the current projection and cannot\n"
+"display a configuration panel.\n"
+"\n"
+"The unidentified set of parameters is:\n"
+"\n"
+msgstr ""
+"Thuban ÎÅ ÚÎÁÅÔ ÐÁÒÁÍÅÔÒÏ× ÄÌÑ ÄÁÎÎÏÊ ÐÒÏÅËÃÉÉ\n"
+"É ÎÅ ÍÏÖÅÔ ÐÏËÁÚÁÔØ\n"
+"ÐÁÎÅÌØ \n"
+"ËÏÎÆÉÇÕÒÁÃÉÉ.\n"
+"\n"
+"îÅÉÚ×ÅÓÔÎÙÊ ÎÁÂÏÒ ÐÁÒÁÍÅÔÒÏ×:\n"
+"\n"
+
+#: ../Thuban/UI/projdialog.py:762
+msgid "Latitude:"
+msgstr "ûÉÒÏÔÁ:"
+
+#: ../Thuban/UI/projdialog.py:764
+msgid "Longitude:"
+msgstr "äÏÌÇÏÔÁ:"
+
+#: ../Thuban/UI/projdialog.py:766 ../Thuban/UI/projdialog.py:910
+msgid "False Easting:"
+msgstr "÷ÏÓÔÏÞÎÏÅ ÏÔËÌÏÎÅÎÉÅ:"
+
+#: ../Thuban/UI/projdialog.py:768 ../Thuban/UI/projdialog.py:912
+msgid "False Northing:"
+msgstr "óÅ×ÅÒÎÏÅ ÏÔËÌÏÎÅÎÉÅ:"
+
+#: ../Thuban/UI/projdialog.py:770
+msgid "Scale Factor:"
+msgstr "íÁÓÛÔÁÂÎÙÊ ÍÎÏÖÉÔÅÌØ:"
+
+#: ../Thuban/UI/projdialog.py:821
+msgid "Propose"
+msgstr "õÓÔÁÎÏ×ÉÔØ"
+
+#: ../Thuban/UI/projdialog.py:823
+msgid "Southern Hemisphere"
+msgstr "àÖÎÏÅ ÐÏÌÕÛÁÒÉÅ"
+
+#: ../Thuban/UI/projdialog.py:833
+msgid "Zone:"
+msgstr "úÏÎÁ:"
+
+#: ../Thuban/UI/projdialog.py:870
+msgid "Can not propose: No bounding box found."
+msgstr "îÅ×ÏÚÍÏÖÎÏ ÐÒÅÄÌÏÖÉÔØ: ÎÅ ÎÁÊÄÅÎ Bounding Box."
+
+#: ../Thuban/UI/projdialog.py:871 ../Thuban/UI/projdialog.py:1008
+msgid "Projection: Propose UTM Zone"
+msgstr "ðÒÏÅËÃÉÑ: ÕÓÔÁÎÏ×ÉÔØ ÚÏÎÕ UTM"
+
+#: ../Thuban/UI/projdialog.py:901
+msgid "Latitude of first standard parallel:"
+msgstr "ûÉÒÏÔÁ ÐÅÒ×ÏÊ ÓÔÁÎÄÁÒÔÎÏÊ ÐÁÒÁÌÌÅÌÉ"
+
+#: ../Thuban/UI/projdialog.py:904
+msgid "Latitude of second standard parallel:"
+msgstr "ûÉÒÏÔÁ ×ÔÏÒÏÊ ÓÔÁÎÄÁÒÔÎÏÊ ÐÁÒÁÌÌÅÌÉ"
+
+#: ../Thuban/UI/projdialog.py:906
+msgid "Central Meridian:"
+msgstr "ãÅÎÔÒÁÌØÎÙÊ ÍÅÒÉÄÉÁÎ:"
+
+#: ../Thuban/UI/projdialog.py:908
+msgid "Latitude of origin:"
+msgstr "ïÓÎÏ×ÎÁÑ ÛÉÒÏÔÁ:"
+
+#: ../Thuban/UI/projdialog.py:958
+msgid "Degrees"
+msgstr "çÒÁÄ."
+
+#: ../Thuban/UI/projdialog.py:959
+msgid "Radians"
+msgstr "òÁÄ."
+
+#: ../Thuban/UI/projdialog.py:992
+msgid "Source Data is in: "
+msgstr "éÓÈÏÄÎÙÅ ÄÁÎÎÙÅ ×: "
+
+#: ../Thuban/UI/projdialog.py:1021
+msgid "The current map extent center lies in UTM Zone"
+msgstr "ãÅÎÔÒ ÒÁÓÐÏÌÏÖÅÎÉÑ ÄÁÎÎÏÊ ËÁÒÔÙ ÎÁÈÏÄÉÔÓÑ × UTM Zone"
+
+#: ../Thuban/UI/projdialog.py:1031
+msgid "Take"
+msgstr "ðÒÉÎÑÔØ"
+
+#: ../Thuban/UI/projlist.py:51
+msgid "Available Projections"
+msgstr "÷ÏÚÍÏÖÎÙÅ ÐÒÏÅËÃÉÉ:"
+
+#: ../Thuban/UI/projlist.py:112
+msgid "<None>"
+msgstr "<îÅÔ>"
+
+#: ../Thuban/UI/projlist.py:117
+#, python-format
+msgid "%s (current)"
+msgstr "%s (ÔÅËÕÝ.)"
+
+#: ../Thuban/UI/rasterlayerproperties.py:41
+msgid "GDAL image information unavailable. See About box for details."
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:49
+#, fuzzy
+msgid "Extent (lat-lon): None"
+msgstr "òÁÚÍÁÈ (ÛÉÒ.-ÄÏÌÇ.):"
+
+#: ../Thuban/UI/rasterlayerproperties.py:56
+#, fuzzy
+msgid "Image Properties"
+msgstr "ó×ÏÊÓÔ×Á ÓÌÏÑ"
+
+#: ../Thuban/UI/rasterlayerproperties.py:61
+#, python-format
+msgid "Source: %s"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:71
+#, fuzzy, python-format
+msgid "Driver: %s"
+msgstr "ðÏÌÅ: %s"
+
+#: ../Thuban/UI/rasterlayerproperties.py:74
+#, python-format
+msgid "Size: %ix%i"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:77
+#, fuzzy, python-format
+msgid "Number of Bands: %i"
+msgstr "þÉÓÌÏ ËÌÁÓÓÏ×:"
+
+#: ../Thuban/UI/rasterlayerproperties.py:93
+msgid "Mask Type"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:99
+msgid "Opacity:"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:381
+msgid "Replace Selection"
+msgstr "îÏ×ÁÑ ×ÙÂÏÒËÁ"
+
+#: ../Thuban/UI/tableview.py:382
+msgid "Refine Selection"
+msgstr "õÔÏÞÎÉÔØ ×ÙÂÏÒËÕ"
+
+#: ../Thuban/UI/tableview.py:383
+msgid "Add to Selection"
+msgstr "äÏÂÁ×ÉÔØ × ×ÙÂÏÒËÕ"
+
+#: ../Thuban/UI/tableview.py:385
+msgid "Query"
+msgstr "úÁÐÒÏÓ"
+
+#: ../Thuban/UI/tableview.py:387
+msgid "Export Selection"
+msgstr "üËÓÐÏÒÔ ×ÙÂÏÒËÉ"
+
+#: ../Thuban/UI/tableview.py:413
+msgid "Selection"
+msgstr "÷ÙÂÏÒËÁ"
+
+#: ../Thuban/UI/tableview.py:455
+#, python-format
+msgid "%i rows (%i selected), %i columns"
+msgstr "%i ÓÔÒÏË (%i ×ÙÂÒÁÎÏ), %i ÓÔÏÌÂÃÏ×"
+
+#: ../Thuban/UI/tableview.py:535
+msgid "Export Table To"
+msgstr "üËÓÐÏÒÔ ÔÁÂÌÉÃÙ"
+
+#: ../Thuban/UI/tableview.py:536
+msgid "DBF Files (*.dbf)|*.dbf|"
+msgstr "æÁÊÌÙ DBF (*.dbf)|*.dbf|"
+
+#: ../Thuban/UI/tableview.py:537
+msgid "CSV Files (*.csv)|*.csv|"
+msgstr "æÁÊÌÙ CSV (*.csv)|*.csv|"
+
+#: ../Thuban/UI/tableview.py:538
+msgid "All Files (*.*)|*.*"
+msgstr "÷ÓÅ ÆÁÊÌÙ (*.*)|*.*"
+
+#: ../Thuban/UI/tree.py:226
+msgid "Session"
+msgstr "óÅÓÓÉÑ"
+
+#: ../Thuban/UI/view.py:285
+msgid "Export Map"
+msgstr "üËÓÐÏÒÔ ËÁÒÔÙ"
+
+#~ msgid "Type: %s"
+#~ msgstr "ôÉÐ: %s"
+
+#~ msgid "Projection: UTM Parameters"
+#~ msgstr "ðÒÏÅËÃÉÑ: ÐÁÒÁÍÅÔÒÙ UTM"
+
+#~ msgid "UTM Zone"
+#~ msgstr "úÏÎÁ UTM"
+
+#~ msgid "Ellipsoid"
+#~ msgstr "üÌÌÉÐÓÏÉÄ"

Added: packages/thuban/branches/upstream/current/po/thuban.pot
===================================================================
--- packages/thuban/branches/upstream/current/po/thuban.pot	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/po/thuban.pot	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1783 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-03-13 20:29+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../Thuban/version.py:189
+#, python-format
+msgid "%s %s < %s"
+msgstr ""
+
+#: ../Thuban/version.py:195
+#, python-format
+msgid "Thuban was compiled with wx %(wxproj-wx)s but wxPython is %(wxPython)s"
+msgstr ""
+
+#: ../Thuban/Lib/connector.py:65
+#, python-format
+msgid "no receivers for channel %s of %s"
+msgstr ""
+
+#: ../Thuban/Lib/connector.py:70
+#, python-format
+msgid "receiver %s%s is not connected to channel %s of %s"
+msgstr ""
+
+#: ../Thuban/Lib/connector.py:94
+#, python-format
+msgid "Warning: %s.%s: %s%s\n"
+msgstr ""
+
+#: ../Thuban/Lib/connector.py:118
+#, python-format
+msgid "\tmethod %s of %s"
+msgstr ""
+
+#: ../Thuban/Lib/fileutil.py:87 ../Thuban/Lib/fileutil.py:141
+msgid "first argument must be an absolute filename"
+msgstr ""
+
+#: ../Thuban/Lib/fileutil.py:138
+msgid "Both parameters must have a drive letter"
+msgstr ""
+
+#: ../Thuban/Lib/fileutil.py:198
+msgid "No implementation of get_application_dir available for platform"
+msgstr ""
+
+#: ../Thuban/Lib/fileutil.py:208
+msgid "No implementation of relative_filename available for platform"
+msgstr ""
+
+#: ../Thuban/Model/classgen.py:338
+msgid "invalid index"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:309 ../Thuban/UI/classifier.py:758
+msgid "None"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:325
+msgid "Line Color"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:327
+#, python-format
+msgid "Line Width: %s"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:333
+#, python-format
+msgid "Size: %s"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:336
+msgid "Fill"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:342 ../Thuban/UI/classifier.py:841
+msgid "Classification"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:436
+msgid "lineWidth < 1"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:451
+msgid "size < 1"
+msgstr ""
+
+#: ../Thuban/Model/classification.py:656 ../Thuban/UI/classifier.py:528
+msgid "DEFAULT"
+msgstr ""
+
+#: ../Thuban/Model/data.py:316
+msgid "Table not compatible with shapestore."
+msgstr ""
+
+#: ../Thuban/Model/extension.py:90
+#, python-format
+msgid "Extension: %s"
+msgstr ""
+
+#: ../Thuban/Model/label.py:91
+#, python-format
+msgid "Number of labels: %d"
+msgstr ""
+
+#: ../Thuban/Model/label.py:92
+#, python-format
+msgid "Label Layer: %s"
+msgstr ""
+
+#: ../Thuban/Model/layer.py:298 ../Thuban/Model/layer.py:566
+#: ../Thuban/Model/session.py:432
+#, python-format
+msgid "Filename: %s"
+msgstr ""
+
+#: ../Thuban/Model/layer.py:301 ../Thuban/Model/layer.py:569
+msgid "Shown"
+msgstr ""
+
+#: ../Thuban/Model/layer.py:303 ../Thuban/Model/layer.py:571
+msgid "Hidden"
+msgstr ""
+
+#: ../Thuban/Model/layer.py:304
+#, python-format
+msgid "Shapes: %d"
+msgstr ""
+
+#: ../Thuban/Model/layer.py:308 ../Thuban/Model/layer.py:575
+#: ../Thuban/Model/map.py:287 ../Thuban/UI/rasterlayerproperties.py:51
+#, python-format
+msgid "Extent (lat-lon): (%g, %g, %g, %g)"
+msgstr ""
+
+#: ../Thuban/Model/layer.py:310 ../Thuban/Model/layer.py:577
+msgid "Extent (lat-lon):"
+msgstr ""
+
+#: ../Thuban/Model/layer.py:311
+#, python-format
+msgid "Shapetype: %s"
+msgstr ""
+
+#: ../Thuban/Model/layer.py:314 ../Thuban/Model/layer.py:580
+#: ../Thuban/Model/map.py:292
+msgid "Projection"
+msgstr ""
+
+#: ../Thuban/Model/layer.py:319 ../Thuban/Model/layer.py:583
+#, python-format
+msgid "Layer '%s'"
+msgstr ""
+
+#: ../Thuban/Model/load.py:78
+#, python-format
+msgid "Invalid hexadecimal color specification %s"
+msgstr ""
+
+#: ../Thuban/Model/load.py:81
+#, python-format
+msgid "Invalid color specification %s"
+msgstr ""
+
+#: ../Thuban/Model/load.py:544
+msgid "xml field type differs from database!"
+msgstr ""
+
+#: ../Thuban/Model/load.py:609
+msgid "Classification range is not a number!"
+msgstr ""
+
+#: ../Thuban/Model/map.py:53
+msgid "Labels"
+msgstr ""
+
+#: ../Thuban/Model/map.py:290
+#, python-format
+msgid "Extent (projected): (%g, %g, %g, %g)"
+msgstr ""
+
+#: ../Thuban/Model/map.py:301
+#, python-format
+msgid "Map: %s"
+msgstr ""
+
+#: ../Thuban/Model/proj.py:84 ../Thuban/Model/resource.py:179
+msgid "Unknown"
+msgstr ""
+
+#: ../Thuban/Model/resource.py:46
+#, python-format
+msgid ""
+"No GDAL support because module '%s' cannot be imported. Python exception: '%"
+"s'"
+msgstr ""
+
+#: ../Thuban/Model/resource.py:135 ../Thuban/Model/resource.py:155
+#, python-format
+msgid "Could not read \"%s\": %s"
+msgstr ""
+
+#: ../Thuban/Model/resource.py:187
+#, python-format
+msgid "Error in projection \"%s\": %s"
+msgstr ""
+
+#: ../Thuban/Model/save.py:352
+msgid "Unsupported group type in classification"
+msgstr ""
+
+#: ../Thuban/Model/session.py:430
+msgid "Filename:"
+msgstr ""
+
+#: ../Thuban/Model/session.py:435
+msgid "Modified"
+msgstr ""
+
+#: ../Thuban/Model/session.py:437
+msgid "Unmodified"
+msgstr ""
+
+#: ../Thuban/Model/session.py:442
+#, python-format
+msgid "Session: %s"
+msgstr ""
+
+#: ../Thuban/Model/session.py:448
+msgid "unnamed session"
+msgstr ""
+
+#: ../Thuban/Model/session.py:450
+msgid "unnamed map"
+msgstr ""
+
+#: ../Thuban/UI/about.py:28
+msgid "About Thuban"
+msgstr ""
+
+#: ../Thuban/UI/about.py:47
+msgid "French"
+msgstr ""
+
+#: ../Thuban/UI/about.py:48
+msgid "German"
+msgstr ""
+
+#: ../Thuban/UI/about.py:50
+msgid "Hungarian"
+msgstr ""
+
+#: ../Thuban/UI/about.py:51
+msgid "Italian"
+msgstr ""
+
+#: ../Thuban/UI/about.py:52
+msgid "Portuguese (Brazilian)"
+msgstr ""
+
+#: ../Thuban/UI/about.py:53
+msgid "Russian"
+msgstr ""
+
+#: ../Thuban/UI/about.py:54
+msgid "Spanish"
+msgstr ""
+
+#: ../Thuban/UI/about.py:63 ../Thuban/UI/about.py:65 ../Thuban/UI/about.py:67
+msgid "- not available"
+msgstr ""
+
+#: ../Thuban/UI/about.py:72
+msgid "Currently using:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:78
+#, python-format
+msgid "\tInternal encoding: %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:84
+msgid "Compiled for:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:90
+msgid "Extensions:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:95 ../Thuban/UI/about.py:144
+msgid "\tNone registered.\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:98
+msgid "Maintainers:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:103
+msgid "Lead Developer:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:106
+msgid "Developers:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:111
+msgid "Translators:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:116
+msgid "Other Contributors:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:122
+msgid ""
+"Questions and comments can be sent to the following addresses:\n"
+"\tGeneral list (public):\n"
+"\t\t<thuban-list at intevation.de>\n"
+"\tDevelopers list (public):\n"
+"\t\t<thuban-devel at intevation.de>\n"
+"\tThuban team at Intevation:\n"
+"\t\t<thuban at intevation.de>\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:130
+msgid ""
+"Details on the registered extensions:\n"
+"\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:135
+#, python-format
+msgid "Copyright %s\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:136
+msgid "Authors:\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:149
+msgid ""
+"Thuban is a program for exploring geographic data.\n"
+"\n"
+msgstr ""
+
+#: ../Thuban/UI/about.py:151
+msgid "Thuban is licensed under the GNU GPL"
+msgstr ""
+
+#: ../Thuban/UI/about.py:160 ../Thuban/UI/classgen.py:91
+#: ../Thuban/UI/dbdialog.py:276 ../Thuban/UI/dock.py:371
+#: ../Thuban/UI/join.py:66 ../Thuban/UI/layerproperties.py:82
+#: ../Thuban/UI/projdialog.py:209 ../Thuban/UI/tableview.py:388
+msgid "Close"
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:24
+#, python-format
+msgid "Select an alternative data file for %s"
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:31 ../Thuban/UI/mainwindow.py:563
+msgid "Shapefiles (*.shp)"
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:32 ../Thuban/UI/mainwindow.py:564
+#: ../Thuban/UI/mainwindow.py:852
+msgid "All Files (*.*)"
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:47
+#, python-format
+msgid ""
+"Found the following as an alternative for %s.\n"
+"%s\n"
+"\n"
+" Please confirm with Yes or select alternative with No."
+msgstr ""
+
+#: ../Thuban/UI/altpathdialog.py:49
+msgid "Alternative Path"
+msgstr ""
+
+#: ../Thuban/UI/application.py:110 ../Thuban/UI/application.py:122
+msgid "Cannot import the thubanstart module\n"
+msgstr ""
+
+#: ../Thuban/UI/application.py:115
+msgid "No thubanstart module available\n"
+msgstr ""
+
+#: ../Thuban/UI/application.py:126
+msgid "No ~/.thuban directory\n"
+msgstr ""
+
+#: ../Thuban/UI/application.py:166
+msgid ""
+"This is the wxPython-based Graphical User Interface for exploring geographic "
+"data"
+msgstr ""
+
+#: ../Thuban/UI/application.py:254
+msgid ""
+"The current session contains Image layers,\n"
+"but the GDAL library is not available to draw them."
+msgstr ""
+
+#: ../Thuban/UI/application.py:259
+msgid "Library not available"
+msgstr ""
+
+#: ../Thuban/UI/application.py:268 ../Thuban/UI/mainwindow.py:476
+msgid "DB Connection Parameters"
+msgstr ""
+
+#: ../Thuban/UI/application.py:364
+#, python-format
+msgid ""
+"An unhandled exception occurred:\n"
+"%s\n"
+"(please report to http://thuban.intevation.org/bugtracker.html)\n"
+"\n"
+"%s"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:43
+msgid "Uniform Distribution"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:44
+msgid "Unique Values"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:45
+msgid "Quantiles from Table"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:47
+msgid "Custom Ramp"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:48
+msgid "Grey Ramp"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:49
+msgid "Red Ramp"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:50
+msgid "Green Ramp"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:51
+msgid "Blue Ramp"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:52
+msgid "Green-to-Red Ramp"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:53
+msgid "Hot-to-Cold Ramp"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:69
+msgid "Generate Classification"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:90
+msgid "Generate"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:119
+#, python-format
+msgid "Field: %s"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:123 ../Thuban/UI/classifier.py:976
+#, python-format
+msgid "Data Type: %s"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:127
+msgid "Generate:"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:137
+msgid "Color Scheme:"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:161
+msgid "Fix Border Color"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:168 ../Thuban/UI/classgen.py:936
+#: ../Thuban/UI/classgen.py:967
+msgid "Change"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:274
+msgid ""
+"Based on the data from the table and the input\n"
+"values, the exact quantiles could not be generated.\n"
+"\n"
+"Accept a close estimate?"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:277
+msgid "Problem with Quantiles"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:370
+msgid "Min:"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:375
+msgid "Max:"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:380 ../Thuban/UI/classgen.py:633
+msgid "Retrieve From Table"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:390
+msgid "Number of Groups:"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:397
+msgid "Stepping:"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:647
+msgid "Available"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:652 ../Thuban/UI/classgen.py:692
+msgid "Sort"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:655 ../Thuban/UI/classgen.py:695
+msgid "Reverse"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:687
+msgid "Use"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:832
+msgid "Retrieve from Table"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:840
+msgid "Apply to Range"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:847
+msgid "Number of Classes:"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:930
+msgid "Start:"
+msgstr ""
+
+#: ../Thuban/UI/classgen.py:961
+msgid "End:"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:164
+msgid "The Default group cannot be removed."
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:309
+#: ../Thuban/UI/classifier.py:467
+msgid "Pattern"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:272 ../Thuban/UI/classifier.py:306
+#: ../Thuban/UI/classifier.py:466
+msgid "Singleton"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Visible"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Symbol"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:317 ../Thuban/UI/controls.py:33
+#: ../Thuban/UI/controls.py:177
+msgid "Value"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:317
+msgid "Label"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:462 ../Thuban/UI/classifier.py:465
+msgid "Default"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:468
+msgid "Range"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:469
+msgid "Map"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:759
+msgid "Text"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:760
+msgid "Integer"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:761
+msgid "Decimal"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:820
+msgid "Generate Class"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:822 ../Thuban/UI/dbdialog.py:274
+msgid "Add"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:824
+msgid "Move Up"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:826
+msgid "Move Down"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:828
+msgid "Edit Symbol"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:830 ../Thuban/UI/dbdialog.py:275
+#: ../Thuban/UI/projdialog.py:117
+msgid "Remove"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:845
+msgid "Field: "
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:1000 ../Thuban/UI/layerproperties.py:160
+msgid "Layer Properties"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:1167
+msgid "Select Properties"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:1178
+msgid "Preview:"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:1195
+msgid "Change Line Color"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:1201 ../Thuban/UI/classifier.py:1216
+msgid "Transparent"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:1212
+msgid "Change Fill Color"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:1225
+msgid "Line Width: "
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:1242
+msgid "Size: "
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:1262 ../Thuban/UI/colordialog.py:52
+#: ../Thuban/UI/dbdialog.py:107 ../Thuban/UI/dbdialog.py:221
+#: ../Thuban/UI/labeldialog.py:41 ../Thuban/UI/layerproperties.py:81
+#: ../Thuban/UI/projdialog.py:205
+msgid "OK"
+msgstr ""
+
+#: ../Thuban/UI/classifier.py:1264 ../Thuban/UI/colordialog.py:53
+#: ../Thuban/UI/dbdialog.py:110 ../Thuban/UI/dbdialog.py:223
+#: ../Thuban/UI/labeldialog.py:42 ../Thuban/UI/projdialog.py:1033
+msgid "Cancel"
+msgstr ""
+
+#: ../Thuban/UI/colordialog.py:39
+msgid "Select Color"
+msgstr ""
+
+#: ../Thuban/UI/controls.py:31
+msgid "Field"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:41
+msgid "Choose layer from database"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:59
+msgid "Databases"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:74
+msgid "Retrieve"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:82
+msgid "Tables"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:92
+msgid "ID Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:98
+msgid "Geometry Column"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:187
+msgid "Hostname:"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:191
+msgid "Port:"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:198
+msgid "Database Name:"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:206
+msgid "User:"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:211
+msgid "Password:"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:286
+msgid "Database Management"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:361 ../Thuban/UI/dbdialog.py:366
+msgid "Add Database"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:367
+#, python-format
+msgid "Connection '%s' already exists"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:388
+msgid "Remove Database Connection"
+msgstr ""
+
+#: ../Thuban/UI/dbdialog.py:389
+#, python-format
+msgid ""
+"The connection %s\n"
+"is still in use"
+msgstr ""
+
+#: ../Thuban/UI/dock.py:190
+msgid "Undock"
+msgstr ""
+
+#: ../Thuban/UI/dock.py:218
+msgid "Dock"
+msgstr ""
+
+#: ../Thuban/UI/exceptiondialog.py:23 ../Thuban/UI/exceptiondialog.py:61
+msgid "Thuban: Internal Error"
+msgstr ""
+
+#: ../Thuban/UI/exceptiondialog.py:43
+msgid "Proceed"
+msgstr ""
+
+#: ../Thuban/UI/exceptiondialog.py:44
+msgid "Exit Thuban now"
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:72
+msgid "Initialization not yet requested."
+msgstr ""
+
+#: ../Thuban/UI/extensionregistry.py:88
+msgid "Initialization successful."
+msgstr ""
+
+#: ../Thuban/UI/identifyview.py:44
+msgid "Identify Shape"
+msgstr ""
+
+#: ../Thuban/UI/identifyview.py:56
+msgid "Close Window"
+msgstr ""
+
+#: ../Thuban/UI/identifyview.py:57
+msgid "Stop Identify Mode"
+msgstr ""
+
+#: ../Thuban/UI/join.py:64
+msgid "Join"
+msgstr ""
+
+#: ../Thuban/UI/join.py:71 ../Thuban/UI/join.py:72
+msgid "Select..."
+msgstr ""
+
+#: ../Thuban/UI/join.py:100 ../Thuban/UI/join.py:108
+msgid "Table:"
+msgstr ""
+
+#: ../Thuban/UI/join.py:111 ../Thuban/UI/join.py:114
+msgid "Field:"
+msgstr ""
+
+#: ../Thuban/UI/join.py:125
+msgid "Outer Join (preserves left table records)"
+msgstr ""
+
+#: ../Thuban/UI/join.py:173
+#, python-format
+msgid ""
+"Join failed:\n"
+"  %s"
+msgstr ""
+
+#: ../Thuban/UI/join.py:174
+msgid "Info"
+msgstr ""
+
+#: ../Thuban/UI/join.py:195
+#, python-format
+msgid ""
+"The joined table has %(joined)d rows but it must have %(needed)d rows to be "
+"used with the selected layer"
+msgstr ""
+
+#: ../Thuban/UI/join.py:200
+msgid "Join Failed"
+msgstr ""
+
+#: ../Thuban/UI/join.py:209 ../Thuban/UI/mainwindow.py:915
+#, python-format
+msgid "Table: %s"
+msgstr ""
+
+#: ../Thuban/UI/labeldialog.py:26
+msgid "Label Values"
+msgstr ""
+
+#: ../Thuban/UI/layerproperties.py:54
+msgid "Title: "
+msgstr ""
+
+#: ../Thuban/UI/layerproperties.py:65
+#, python-format
+msgid "Layer Type: %s"
+msgstr ""
+
+#: ../Thuban/UI/layerproperties.py:71
+msgid "Projection: None"
+msgstr ""
+
+#: ../Thuban/UI/layerproperties.py:73
+#, python-format
+msgid "Projection: %s"
+msgstr ""
+
+#: ../Thuban/UI/layerproperties.py:79 ../Thuban/UI/projdialog.py:199
+msgid "Try"
+msgstr ""
+
+#: ../Thuban/UI/layerproperties.py:80 ../Thuban/UI/projdialog.py:202
+msgid "Revert"
+msgstr ""
+
+#: ../Thuban/UI/legend.py:75
+msgid "Top Layer"
+msgstr ""
+
+#: ../Thuban/UI/legend.py:79
+msgid "Raise Layer"
+msgstr ""
+
+#: ../Thuban/UI/legend.py:83
+msgid "Lower Layer"
+msgstr ""
+
+#: ../Thuban/UI/legend.py:87
+msgid "Bottom Layer"
+msgstr ""
+
+#: ../Thuban/UI/legend.py:91
+msgid "Show Layer"
+msgstr ""
+
+#: ../Thuban/UI/legend.py:95
+msgid "Hide Layer"
+msgstr ""
+
+#: ../Thuban/UI/legend.py:99
+msgid "Edit Layer Properties"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:264 ../Thuban/UI/mainwindow.py:286
+#, python-format
+msgid "Unknown command %s"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:299
+#, python-format
+msgid "Unknown command ID %d"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:338
+#, python-format
+msgid "The Dialog named %s is already open"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:396
+#, python-format
+msgid "Select layer '%s' and pick a projection using Layer/Projection..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:449
+msgid "Exit"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:450
+msgid "The session has been modified. Do you want to save it?"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:465
+msgid "Open Session"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:487
+msgid "Save Session As"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:561
+msgid "Select one or more data files"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:576
+msgid "Add Layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:577 ../Thuban/UI/mainwindow.py:602
+#: ../Thuban/UI/mainwindow.py:862
+#, python-format
+msgid "Can't open the file '%s'."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:589
+msgid "Select an image file"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:601
+msgid "Add Image Layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:629
+msgid "Add Layer from database"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:630
+#, python-format
+msgid "Can't open the database table '%s'"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:719
+#, python-format
+msgid "Copy of `%s'"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:749
+#, python-format
+msgid "Layer Table: %s"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:764
+#, python-format
+msgid "Map Projection: %s"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:779
+#, python-format
+msgid "Layer Projection: %s"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:812
+msgid "Join Layer with Table"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:834 ../Thuban/UI/mainwindow.py:1165
+msgid "Legend"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:848 ../Thuban/UI/mainwindow.py:861
+msgid "Open Table"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:850
+msgid "DBF Files (*.dbf)"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:873
+msgid "Pick the tables to close:"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:874
+msgid "Close Table"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:894
+msgid "Pick the table to show:"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:895
+msgid "Show Table"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:906
+msgid "Join Tables"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:929
+msgid "Pick the table to rename:"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:930 ../Thuban/UI/mainwindow.py:942
+msgid "Rename Table"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:942
+msgid "Table Title:"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:991
+msgid "Map Title:"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:991
+msgid "Rename Map"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1004
+msgid "Layer Title:"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1004
+msgid "Rename Layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1057
+#, python-format
+msgid "Thuban - %s"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1059
+msgid "Thuban"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1154
+msgid "&New Session"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1155
+msgid "Start a new session"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1156
+msgid "&Open Session..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1157
+msgid "Open a session file"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1158
+msgid "&Save Session"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1159
+msgid "Save this session to the file it was opened from"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1160
+msgid "Save Session &As..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1161
+msgid "Save this session to a new file"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1162
+msgid "Session &Tree"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1164
+msgid "Toggle on/off the session tree analysis window"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1167
+msgid "Toggle Legend on/off"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1168
+msgid "&Database Connections..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1171
+msgid "E&xit"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1172
+msgid "Finish working with Thuban"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1175
+msgid "&About..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1176
+msgid "Info about Thuban authors, version and modules"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1180 ../Thuban/UI/mainwindow.py:1228
+msgid "Pro&jection..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1181
+msgid "Set or change the map projection"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1183
+msgid "&Zoom in"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1184
+msgid "Switch to map-mode 'zoom-in'"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1186
+msgid "Zoom &out"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1187
+msgid "Switch to map-mode 'zoom-out'"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1189
+msgid "&Pan"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1190
+msgid "Switch to map-mode 'pan'"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1192
+msgid "&Identify"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1194
+msgid "Switch to map-mode 'identify'"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1196
+msgid "&Label"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1197
+msgid "Add/Remove labels"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1199
+msgid "&Full extent"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1200
+msgid "Zoom to the full map extent"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1202
+msgid "&Full layer extent"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1203
+msgid "Zoom to the full layer extent"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1205
+msgid "&Full selection extent"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1207
+msgid "Zoom to the full selection extent"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1209
+msgid "E&xport"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1210
+msgid "Export the map to file"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1211
+msgid "Prin&t"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1212
+msgid "Print the map"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1213 ../Thuban/UI/mainwindow.py:1299
+msgid "&Rename..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1214
+msgid "Rename the map"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1215
+msgid "&Add Layer..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1216
+msgid "Add a new layer to the map"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1217
+msgid "&Add Image Layer..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1218
+msgid "Add a new image layer to the map"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1220
+msgid "Add &Database Layer..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1221
+msgid "Add a new database layer to active map"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1223
+msgid "&Remove Layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1224
+msgid "Remove selected layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1230
+msgid "Specify projection for selected layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1231
+msgid "&Duplicate"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1232
+msgid "Duplicate selected layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1234
+msgid "Re&name ..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1235
+msgid "Rename selected layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1237
+msgid "&Raise"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1238
+msgid "Raise selected layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1240
+msgid "&Lower"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1241
+msgid "Lower selected layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1243
+msgid "&Show"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1244
+msgid "Make selected layer visible"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1246
+msgid "&Hide"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1247
+msgid "Make selected layer unvisible"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1249
+msgid "Show Ta&ble"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1250
+msgid "Show the selected layer's table"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1252
+msgid "&Properties..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1254
+msgid "Edit the properties of the selected layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1255
+msgid "&Join Table..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1257
+msgid "Join and attach a table to the selected layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1260
+msgid "&Top"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1261
+msgid "Put selected layer to the top"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1263
+msgid "&Bottom"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1264
+msgid "Put selected layer to the bottom"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1266
+msgid "&Visible"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1268
+msgid "Toggle visibility of selected layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1285
+msgid "&Unjoin Table..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1287
+msgid "Undo the last join operation"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1294
+msgid "&Open..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1295
+msgid "Open a DBF-table from a file"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1296
+msgid "&Close..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1298
+msgid "Close one or more tables from a list"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1301
+msgid "Rename one or more tables"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1302
+msgid "&Show..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1304
+msgid "Show one or more tables in a dialog"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1305
+msgid "&Join..."
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1307
+msgid "Join two tables creating a new one"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1331
+msgid "&File"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1337
+msgid "&Map"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1338
+msgid "&Layer"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1352
+msgid "&Table"
+msgstr ""
+
+#: ../Thuban/UI/mainwindow.py:1358
+msgid "&Help"
+msgstr ""
+
+#: ../Thuban/UI/menu.py:90
+#, python-format
+msgid "Submenu %s doesn't exist"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:62 ../Thuban/UI/projdialog.py:776
+msgid "Transverse Mercator"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:63 ../Thuban/UI/projdialog.py:842
+msgid "Universal Transverse Mercator"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:64 ../Thuban/UI/projdialog.py:918
+msgid "Lambert Conic Conformal"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:65 ../Thuban/UI/projdialog.py:66
+#: ../Thuban/UI/projdialog.py:968
+msgid "Geographic"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:110
+msgid "Import..."
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:113
+msgid "Export..."
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:122
+msgid "Show EPSG:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:124
+msgid "Normal"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:127
+msgid "Deprecated"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:138
+msgid "Edit"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:148
+msgid "Name:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:156
+msgid "Projection:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:167 ../Thuban/UI/projdialog.py:648
+msgid "<Unknown>"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:183
+msgid "New"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:186
+msgid "Add to List"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:190
+msgid "Update"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:295
+#, python-format
+msgid ""
+"Warnings when reading \"%s\":\n"
+"\n"
+"%s"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:306
+msgid "Import"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:319 ../Thuban/UI/projdialog.py:617
+msgid "Warnings"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:337 ../Thuban/UI/tableview.py:386
+msgid "Export"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:389
+msgid "The following error occured:\n"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:391
+msgid "Error"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:460
+msgid "No Projections selected"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:470
+#, python-format
+msgid "Source of Projection: %s"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:502
+msgid "Multiple Projections selected"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:649
+msgid "Airy"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:650
+msgid "Bessel 1841"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:651
+msgid "Clarke 1866"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:652
+msgid "Clarke 1880"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:653
+msgid "GRS 1980 (IUGG, 1980)"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:654
+msgid "International 1909 (Hayford)"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:655
+msgid "WGS 84"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:667
+msgid "Ellipsoid:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:716
+msgid ""
+"Thuban does not know the parameters\n"
+"for the current projection and cannot\n"
+"display a configuration panel.\n"
+"\n"
+"The unidentified set of parameters is:\n"
+"\n"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:762
+msgid "Latitude:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:764
+msgid "Longitude:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:766 ../Thuban/UI/projdialog.py:910
+msgid "False Easting:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:768 ../Thuban/UI/projdialog.py:912
+msgid "False Northing:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:770
+msgid "Scale Factor:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:821
+msgid "Propose"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:823
+msgid "Southern Hemisphere"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:833
+msgid "Zone:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:870
+msgid "Can not propose: No bounding box found."
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:871 ../Thuban/UI/projdialog.py:1008
+msgid "Projection: Propose UTM Zone"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:901
+msgid "Latitude of first standard parallel:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:904
+msgid "Latitude of second standard parallel:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:906
+msgid "Central Meridian:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:908
+msgid "Latitude of origin:"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:958
+msgid "Degrees"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:959
+msgid "Radians"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:992
+msgid "Source Data is in: "
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:1021
+msgid "The current map extent center lies in UTM Zone"
+msgstr ""
+
+#: ../Thuban/UI/projdialog.py:1031
+msgid "Take"
+msgstr ""
+
+#: ../Thuban/UI/projlist.py:51
+msgid "Available Projections"
+msgstr ""
+
+#: ../Thuban/UI/projlist.py:112
+msgid "<None>"
+msgstr ""
+
+#: ../Thuban/UI/projlist.py:117
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:41
+msgid "GDAL image information unavailable. See About box for details."
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:49
+msgid "Extent (lat-lon): None"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:56
+msgid "Image Properties"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:61
+#, python-format
+msgid "Source: %s"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:71
+#, python-format
+msgid "Driver: %s"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:74
+#, python-format
+msgid "Size: %ix%i"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:77
+#, python-format
+msgid "Number of Bands: %i"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:93
+msgid "Mask Type"
+msgstr ""
+
+#: ../Thuban/UI/rasterlayerproperties.py:99
+msgid "Opacity:"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:381
+msgid "Replace Selection"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:382
+msgid "Refine Selection"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:383
+msgid "Add to Selection"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:385
+msgid "Query"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:387
+msgid "Export Selection"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:413
+msgid "Selection"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:455
+#, python-format
+msgid "%i rows (%i selected), %i columns"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:535
+msgid "Export Table To"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:536
+msgid "DBF Files (*.dbf)|*.dbf|"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:537
+msgid "CSV Files (*.csv)|*.csv|"
+msgstr ""
+
+#: ../Thuban/UI/tableview.py:538
+msgid "All Files (*.*)|*.*"
+msgstr ""
+
+#: ../Thuban/UI/tree.py:226
+msgid "Session"
+msgstr ""
+
+#: ../Thuban/UI/view.py:285
+msgid "Export Map"
+msgstr ""

Added: packages/thuban/branches/upstream/current/setup.cfg
===================================================================
--- packages/thuban/branches/upstream/current/setup.cfg	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/setup.cfg	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,16 @@
+[sdist]
+formats=bztar,zip
+
+[bdist_rpm]
+release = 1
+doc_files = README 
+	libraries/pyshapelib/README.pyshapelib 
+	libraries/pyshapelib/COPYING.pyshapelib
+	libraries/pyprojection/LICENSE.pyprojection
+prep_script = bdist_rpm_prep
+build_script = bdist_rpm_build
+install_script = bdist_rpm_install
+prefix = /usr
+
+[bdist_inno]
+copyright = Copyright © 2001-2003 Intevation GmbH

Added: packages/thuban/branches/upstream/current/setup.py
===================================================================
--- packages/thuban/branches/upstream/current/setup.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/setup.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1220 @@
+# Copyright (c) 2001, 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""Distutils setup script for Thuban."""
+
+__version__ = "$Revision: 2729 $"
+
+# Configuration:
+#
+# depending on your platform you may have to configure some variables by
+# hand below.
+#
+
+import sys
+import os
+from types import TupleType
+import glob
+from distutils.core import setup, Extension, Command
+from distutils.command.install import install, INSTALL_SCHEMES, subst_vars
+from distutils.command.build_py import build_py
+from distutils.command.bdist_rpm import bdist_rpm
+from distutils.command.build_ext import build_ext
+from distutils.file_util import write_file
+from distutils.filelist import FileList
+from distutils.util import convert_path, change_root
+
+from distutils import archive_util, dir_util
+import distutils
+
+from string import split
+import string
+
+# config script parameter list indices
+CS_DEFS, CS_INCDIRS, CS_LIBDIRS, CS_LIBS, CS_NUM_PARAMS = range(5)
+
+# support for gdal is on by default, but under posix we try to
+# detect it anyway. Set this to False to disable GDAL.
+include_gdal = True
+
+if os.name == "posix":
+    ###################################################################
+    # Posix configuration. Adapt this if you're running some kind of
+    # Unix like system.
+   
+    # Directories where Proj4 is installed
+    proj4_prefix = "/usr/local/"
+    proj4_incdir =  os.path.join(proj4_prefix, "include")
+    proj4_libdir =  os.path.join(proj4_prefix, "lib")
+    proj4_lib = "proj"
+
+
+    # You shouldn't have to modify anything below here
+    ###################################################################
+    
+    # The installation prefix (similar to autoconf's --prefix). This is
+    # only the default value, you can override it on the command line
+    # with the install command's --prefix option.
+    # 
+    # Note that there's a separate prefix option for the bdist_rpm
+    # command completely independent of this one.
+    prefix = "/usr/local/"
+
+    # Whether to create the thubaninit module. You can override this
+    # value on the commandline with the --create-init-module to the
+    # install command.
+    create_init_module = 1
+
+    # On POSIX-systems we run wxgtk-config to determine the C++-compiler
+    # flags
+    wx_config_script = "wx-config"
+    # These lists will be filled automatically below
+    wx_cs_params = [[] for i in range(CS_NUM_PARAMS)]
+
+    gdal_config_script = "gdal-config"
+    gdal_cs_params = [[] for i in range(CS_NUM_PARAMS)]
+
+elif os.name == "nt":
+    #################################################################
+    # Windows configuration.
+    #
+
+    basedir = os.path.dirname(sys.argv[0])
+
+    # Directories where Proj4 is installed
+    proj4_prefix = os.path.join(basedir, "..", "proj-4.4.9", "src")
+    proj4_incdir =  proj4_prefix
+    proj4_libdir =  proj4_prefix
+    proj4_lib = "proj_i"
+
+    # Define include and lib directories for wxWindows and 
+    wx_prefix = os.path.join(basedir, "..", "wxPython-2.6.3.3")
+    wx_inc = [os.path.join(wx_prefix, 'lib', 'vc_dll', 'mswuh'),
+              os.path.join(wx_prefix, "include")]
+    wx_lib = [os.path.join(wx_prefix, "lib", "vc_dll")]
+
+    # Define include and lib directories for GDAL 
+    gdal_prefix = os.path.join(basedir, "..", "gdal-1.3.2")
+    gdal_inc = [os.path.join(gdal_prefix, 'alg'),
+                os.path.join(gdal_prefix, 'ogr'),
+                os.path.join(gdal_prefix, 'port'),
+                os.path.join(gdal_prefix, 'gcore'),
+                os.path.join(gdal_prefix, 'core')]
+    gdal_lib = [gdal_prefix]
+
+    #
+    # Unless you use a wxPython version other than 2.4.0, you probably
+    # shouldn't have to modify anything below here
+    ##################################################################
+    
+    # Installation prefix. Just install relative to current directory by
+    # default. This is only the default value, you can override it on
+    # the command line with the install command's --prefix option
+    prefix = r"install"
+
+    # Whether to create the thubaninit module. You can override this
+    # value on the commandline with the --create-init-module to the
+    # install command. By default we don't create it under NT because we
+    # most often run install only as part of bdist_inno where we can't
+    # really create because it needs information only known at install
+    # time.
+    create_init_module = 0
+
+    # There doesn't seem to be an easy way to get at the wx compiler
+    # flags, so we define them here. These flags work for us with
+    # wxPython 2.3.1. They may have to be modified for other versions.
+
+    # there's no config script.
+    wx_config_script = ""
+    
+    wx_cs_params = [[] for i in range(CS_NUM_PARAMS)]
+
+    # the values of wx_defs and wx_libs. copied from the wxPython
+    # setup.py
+    wx_cs_params[CS_DEFS] = \
+              [ ('WIN32', None),        # Some of these are no longer
+                ('__WIN32__', None),    # necessary.  Anybody know which?
+                ('_WINDOWS', None),
+                ('__WINDOWS__', None),
+                ('WINVER', '0x0400'),
+                ('__WIN95__', None),
+                ('STRICT', None),
+
+                ('__WXMSW__', None),
+                ('WXUSINGDLL', '1'),
+
+                ('SWIG_GLOBAL', None),
+                ('HAVE_CONFIG_H', None),
+                ('WXP_USE_THREAD', '1'),
+                ]
+    
+    wx_cs_params[CS_INCDIRS] = wx_inc
+    wx_cs_params[CS_LIBDIRS] = wx_lib
+    wx_cs_params[CS_LIBS] = ["wxmsw26uh"] \
+                      + ['kernel32', 'user32', 'gdi32', 'comdlg32',
+                         'winspool', 'winmm', 'shell32', 'oldnames',
+                         'comctl32', 'odbc32', 'ole32', 'oleaut32',
+                         'uuid', 'rpcrt4', 'advapi32', 'wsock32']
+
+    gdal_config_script = ""
+    gdal_cs_params = [[] for i in range(CS_NUM_PARAMS)]
+
+    gdal_cs_params[CS_INCDIRS] = gdal_inc
+    gdal_cs_params[CS_LIBDIRS] = gdal_lib
+    gdal_cs_params[CS_LIBS] = ["gdal_i"]
+
+else:
+    raise RuntimeError("Unsupported platform " + os.name)
+
+
+######################################################################
+#
+#  There's nothing beyond this point that has to be modified for a
+#  normal installation
+#
+######################################################################
+
+
+#
+#   Functions to determine wxWindows config on POSIX systems
+#
+
+def run_script(cmdline):
+    """Run command and return its stdout or none in case of errors"""
+    pipe = os.popen(cmdline)
+    result = pipe.read()
+    if pipe.close() is not None:
+        print '"' + cmdline + '"', 'failed'
+        return None
+    return result
+
+
+def run_cs_script(command, store):
+    # first, determine the C++ preprocessor flags Use --cflags here
+    # because it seems that older version don't have --cxxflags and
+    # newer ones return the same result for both
+    flags = run_script(command + ' --cflags ')
+    if flags is None:
+        return False
+    for flag in split(flags):
+        start = flag[:2]
+        value = flag[2:]
+        if start == "-I":
+            store[CS_INCDIRS].append(value)
+        elif start == "-D":
+            store[CS_DEFS].append((value, None))
+
+    # determine the library flags
+    flags = run_script(command + ' --libs')
+    if flags is None:
+        return False
+    for flag in split(flags):
+        start = flag[:2]
+        value = flag[2:]
+        if start == "-L":
+            store[CS_LIBDIRS].append(value)
+        elif start == "-l":
+            store[CS_LIBS].append(value)
+
+    return True
+
+if wx_config_script:
+    # if there's a wx config script, run it to determine the configuration
+    run_cs_script(wx_config_script, wx_cs_params)
+
+if gdal_config_script:
+    # if there's a gdal config script, run it to determine the configuration
+    include_gdal = include_gdal \
+                   and run_cs_script(gdal_config_script, gdal_cs_params)
+
+#
+# Define some extension and python modules
+#
+# The C-extension names are prefixed with "Lib." so they get put into
+# the Lib/ subdirectory. Lib/ is not really a package but distutils
+# doesn't care
+
+# subdirectory containing the distutil extensions
+ext_dir = "libraries"
+
+# subdirectory with some shapelib files
+shp_dir = ext_dir + "/shapelib"
+
+# lists to fill with the module descriptions
+extensions = []
+py_modules = []
+
+
+#
+# Thuban specific modules
+#
+
+wxproj_extension = Extension("Lib.wxproj",
+                             [ext_dir + "/thuban/wxproj.cpp"],
+                             include_dirs = ([shp_dir, proj4_incdir,
+                                              ext_dir + "/pyshapelib/"]
+                                             + wx_cs_params[CS_INCDIRS]),
+                             define_macros = wx_cs_params[CS_DEFS],
+                             library_dirs = [proj4_libdir] + 
+                             wx_cs_params[CS_LIBDIRS],
+                             libraries = [proj4_lib] + wx_cs_params[CS_LIBS])
+extensions.append(wxproj_extension)
+
+
+#
+# shapelib wrappers are also distributed with thuban
+#
+
+extensions.append(Extension("Lib.shapelibc",
+                            [ext_dir + "/pyshapelib/shapelib_wrap.c",
+                             shp_dir + "/shpopen.c",
+                             shp_dir + "/shptree.c"],
+                            include_dirs = [shp_dir]))
+extensions.append(Extension("Lib.shptree",
+                            [ext_dir + "/pyshapelib/shptreemodule.c"],
+                            include_dirs = [shp_dir]))
+extensions.append(Extension("Lib.dbflibc",
+                            [ext_dir + "/pyshapelib/dbflib_wrap.c",
+                             shp_dir + "/dbfopen.c"],
+                            include_dirs = [shp_dir],
+                            define_macros = [("HAVE_UPDATE_HEADER", "1")]))
+for name in ("shapelib", "dbflib"):
+    py_modules.append(ext_dir + "/pyshapelib/" + name)
+
+#
+# PROJ4 bindings are also distributed with thuban
+#
+extensions.append(Extension("Lib.Projectionc",
+                            [ext_dir + "/pyprojection/Projection_wrap.c"],
+                            include_dirs = [proj4_incdir],
+                            library_dirs = [proj4_libdir],
+                            libraries = [proj4_lib]))
+py_modules.append(ext_dir + "/pyprojection/Projection")
+
+
+#
+#  Data files
+#
+
+data_files = []
+
+# Resources
+for d, patterns in [("Resources/Bitmaps",
+                    ("Resources/Bitmaps/*.xpm",)),
+                   ("Resources/Projections",
+                    ("Resources/Projections/*.proj",)),
+                   ("Resources/XML",
+                    ("Resources/XML/*.dtd",)),
+                   ("Extensions/importAPR/samples",
+                    ("Extensions/importAPR/samples/README",
+                     "Extensions/importAPR/samples/*.apr")),
+                   ]:
+    for pattern in patterns:
+        data_files.append((d, glob.glob(pattern)))
+if os.path.isdir("Resources/Locale"):
+    for d in os.listdir("Resources/Locale"):
+        data_files.append(("Resources/Locale/" + d +"/LC_MESSAGES",
+                           ["Resources/Locale/"+ d +"/LC_MESSAGES/thuban.mo"]))
+
+#add the Lib content to the output
+if os.path.isdir("Lib"):
+	for d in os.listdir("Lib"):
+		data_files.append(("Lib", ["Lib/"+d]))
+
+
+#
+#       Command definitions
+#
+# So far distutils are only meant to distribute python extensions, not
+# complete applications, so we have to redefine a few commands
+#
+
+
+# Much of the data_dist command is directly copied from the distutils'
+# sdist command
+class data_dist(Command):
+
+    description = "create a data distribution (tarball, zip file, etc.)"
+
+    user_options = [
+        ('formats=', None,
+         "formats for source distribution (comma-separated list)"),
+        ('keep-temp', 'k',
+         "keep the distribution tree around after creating " +
+         "archive file(s)"),
+        ('dist-dir=', 'd',
+         "directory to put the source distribution archive(s) in "
+         "[default: dist]"),
+        ]
+
+    boolean_options = ['keep-temp']
+
+    def initialize_options (self):
+        self.formats = None
+        self.keep_temp = 0
+        self.dist_dir = None
+
+    def finalize_options (self):
+        self.ensure_string_list('formats')
+        if self.formats is None:
+            self.formats = ["zip"]
+        bad_format = archive_util.check_archive_formats(self.formats)
+        if bad_format:
+            raise DistutilsOptionError, \
+                  "unknown archive format '%s'" % bad_format
+
+        if self.dist_dir is None:
+            self.dist_dir = "dist"
+
+
+    def run(self):
+        # 'filelist' contains the list of files that will make up the
+        # manifest
+        self.filelist = FileList()
+        
+        # Do whatever it takes to get the list of files to process.
+        # File list is accumulated in 'self.filelist'.
+        self.get_file_list()
+
+        # Otherwise, go ahead and create the source distribution tarball,
+        # or zipfile, or whatever.
+        self.make_distribution()
+
+    def get_file_list(self):
+        """Figure out the list of files to include in the data
+        distribution, and put it in 'self.filelist'.
+        """
+        self.filelist.findall("Data")
+        self.filelist.include_pattern("*", anchor = 0)
+        self.filelist.exclude_pattern(r'/(RCS|CVS)/.*', is_regex=1)
+        self.filelist.sort()
+        self.filelist.remove_duplicates()
+
+    def make_release_tree(self, base_dir, files):
+        """Create the directory tree that will become the source
+        distribution archive.  All directories implied by the filenames in
+        'files' are created under 'base_dir', and then we hard link or copy
+        (if hard linking is unavailable) those files into place.
+        Essentially, this duplicates the developer's source tree, but in a
+        directory named after the distribution, containing only the files
+        to be distributed.
+        """
+        # Create all the directories under 'base_dir' necessary to
+        # put 'files' there; the 'mkpath()' is just so we don't die
+        # if the manifest happens to be empty.
+        self.mkpath(base_dir)
+        dir_util.create_tree(base_dir, files,
+                             verbose=self.verbose, dry_run=self.dry_run)
+
+        # And walk over the list of files, either making a hard link (if
+        # os.link exists) to each one that doesn't already exist in its
+        # corresponding location under 'base_dir', or copying each file
+        # that's out-of-date in 'base_dir'.  (Usually, all files will be
+        # out-of-date, because by default we blow away 'base_dir' when
+        # we're done making the distribution archives.)
+    
+        if hasattr(os, 'link'):        # can make hard links on this system
+            link = 'hard'
+            msg = "making hard links in %s..." % base_dir
+        else:                           # nope, have to copy
+            link = None
+            msg = "copying files to %s..." % base_dir
+
+        if not files:
+            self.warn("no files to distribute -- empty manifest?")
+        else:
+            self.announce(msg)
+        for file in files:
+            if not os.path.isfile(file):
+                self.warn("'%s' not a regular file -- skipping" % file)
+            else:
+                dest = os.path.join(base_dir, file)
+                self.copy_file(file, dest, link=link)
+
+
+    def make_distribution (self):
+        """Create the source distribution(s).  First, we create the release
+        tree with 'make_release_tree()'; then, we create all required
+        archive files (according to 'self.formats') from the release tree.
+        Finally, we clean up by blowing away the release tree (unless
+        'self.keep_temp' is true).  The list of archive files created is
+        stored so it can be retrieved later by 'get_archive_files()'.
+        """
+        # Don't warn about missing meta-data here -- should be (and is!)
+        # done elsewhere.
+        base_dir = "Thuban-data-" + self.distribution.get_version()
+        base_name = os.path.join(self.dist_dir, base_dir)
+
+        self.make_release_tree(base_dir, self.filelist.files)
+        archive_files = []              # remember names of files we create
+        for fmt in self.formats:
+            file = self.make_archive(base_name, fmt, base_dir=base_dir)
+            archive_files.append(file)
+
+        self.archive_files = archive_files
+
+        if not self.keep_temp:
+            dir_util.remove_tree(base_dir, self.verbose, self.dry_run)
+
+
+
+class InstallLocal(Command):
+
+    """
+    A new install command to just link (or copy, on non-POSIX systems)
+    the extension modules to the top directory so that Thuban can be run
+    directly from the source dir.
+    """
+
+    description =\
+        "Create some symlinks so you can run thuban from the source directory"
+
+    user_options = [
+        ('skip-build', None, "skip the build steps"),
+        ('create-init-module', None,
+         "Create the thubaninit.py module to ease use of Thuban as a library"),
+        ('dont-create-init-module', None,
+         "Do not create the thubaninit.py module"),
+        ]
+
+    boolean_options = ["create-init-module"]
+    negative_opt = {'dont-create-init-module' : 'create-init-module'}
+
+
+    def initialize_options (self):
+        self.extensions = None
+        self.build_dir = None
+        self.skip_build = None
+        self.create_init_module = None
+
+    def finalize_options (self):
+        self.set_undefined_options("install",
+                                   ("build_lib", "build_dir"),
+                                   ('skip_build', 'skip_build'))
+        self.extensions = self.distribution.ext_modules
+        if self.create_init_module is None:
+            # by default we create the init module
+            self.create_init_module = 1
+
+    def run(self):
+        # Make sure we have built everything we need first
+        self.build()
+
+        # now do the work. Simply link or copy the Lib dir
+        libdir = os.path.join(self.build_dir, "Lib")
+        if os.name == "posix":
+            # on posix, just link the Lib dir
+            self.link_dir(libdir, "Lib")
+        else:
+            self.copy_tree(libdir, "Lib")
+
+        # create the init module if desired
+        if self.create_init_module:
+            # create the init module
+            initfilename = "thubaninit.py"
+            contents = thubaninit_contents("")
+            self.execute(write_file, (initfilename, contents),
+                         "Create %s" % initfilename)
+
+    def link_dir(self, src, dest):
+        """Create a symbolic link dest pointing to src"""
+        if self.verbose:
+            self.announce("symlinking %s -> %s" % (src, dest))
+        if self.dry_run:
+            return
+
+        if not (os.path.exists(dest) and os.path.samefile(src, dest)):
+            os.symlink(src, dest)
+
+    def build (self):
+        if not self.skip_build:
+            if self.distribution.has_pure_modules():
+                self.run_command('build_py')
+            if self.distribution.has_ext_modules():
+                self.run_command('build_ext')
+
+
+
+class thuban_build_py(build_py):
+
+    """
+    A new build_py that can deal with both packages and modules in one
+    distribution.
+    """
+
+    # FIXME: When Thuban can rely on Python 2.3 as the oldest supported
+    # Python release we don't need to override the run and
+    # find_all_modules methods anymore. distutils will allow both python
+    # modules and packages starting with 2.3.
+
+    def run(self):
+        """The same the as the original in build_py revision 1.33 except
+        that this allows both packages and modules to be in one
+        distribution
+        """
+        if not self.py_modules and not self.packages:
+            return
+
+        # Now we're down to two cases: 'py_modules' only and 'packages' only.
+        if self.py_modules:
+            self.build_modules()
+        if self.packages:
+            self.build_packages()
+
+        self.byte_compile(self.get_outputs(include_bytecode=0))
+
+    def find_modules (self):
+        """Thuban specific version of build_py.find_modules. Unlike the
+        original version, we assume that the modules in self.py_modules
+        can contain directories and are all to be placed into the same
+        subdirectory, Lib, in the build directory. This is achieved by
+        returning the modules as a list (package, module, filename)
+        where package is 'Lib', module is the basename of the module name
+        and filename is the filename relative to the package root.
+        """
+        modules = []
+        for module in self.py_modules:
+            module_base = os.path.basename(module)
+            module_file = module + ".py"
+            if not self.check_module(module, module_file):
+                continue
+
+            modules.append(("Lib", module_base, module_file))
+        return modules
+
+    def find_all_modules (self):
+        # same as find_all_modules of the original build_py command
+        # (rev. 1.33) but handle installations with both modules and
+        # packages. Needed here so tha the get_outputs works correctly
+        modules = []
+        if self.py_modules:
+            modules.extend(self.find_modules())
+        if self.packages:
+            for package in self.packages:
+                package_dir = self.get_package_dir(package)
+                m = self.find_package_modules(package, package_dir)
+                modules.extend(m)
+
+        return modules
+
+
+thubaninit_contents_start = """
+# This module was automatically generated by Thuban's install script
+'''Import this module once per program (best place is probably the file
+that ends up as your __main__ module) to be able to import Thuban
+afterwards.
+
+Usage:
+
+import thubaninit
+import Thuban
+'''
+import sys, os
+"""
+
+thubaninit_contents_thubaninitdir = """
+sys.path.insert(0, %(thubandir)s)
+"""
+thubaninit_contents_otherdirs = """
+# Put the Lib dir into the path. The Lib dir contains some extra Python
+# modules
+import Thuban
+thubandir = os.path.join(Thuban.__path__[0], '..')
+dir = os.path.join(thubandir, "Lib")
+if os.path.isdir(dir):
+    sys.path.insert(0, dir)
+"""
+
+def thubaninit_contents(thubandir):
+    """Return the contents of the the thubaninit file as a list of lines.
+
+    The parameter thubandir is the parent directory where the Thuban/
+    package or the empty string if the thubaninit file itself will be
+    located in that direcory as well.
+    """
+    contents = thubaninit_contents_start
+    if thubandir:
+        thubandir = repr(thubandir)
+        contents += thubaninit_contents_thubaninitdir % locals()
+    contents += thubaninit_contents_otherdirs
+    return contents.split("\n")
+
+
+class ThubanInstall(install):
+
+    """
+    Thuban specific install command.
+
+    Extend the standard install command to symlink the installed script
+    to $prefix/bin/
+    """
+
+    user_options = install.user_options[:]
+    user_options.extend([("do-symlink", None,
+                          "Create a symlink to the script in <prefix>/bin."
+                        "(default on posix systems and only relevant there)"),
+
+                         ("extra-files", None,
+                          "List of filenames or (src, dest) pairs describing"
+                          " extra files to install "
+                          "(can only be set from within setup.py"),
+
+                         ("create-init-module=", None,
+                          "If true, create a module in the site-packages"
+                          " directory that tweaks sys.path to let you easily"
+                          " import thuban modules from outside of thuban."),
+                         ("init-module-dir=", None,
+                          "Directory in which to create the init module."
+                          " Defaults to Python's site-packages directory."),
+                         ])
+
+    boolean_options = install.boolean_options[:]
+    boolean_options.append("do-symlink")
+    boolean_options.append("create-init-module")
+
+    def initialize_options(self):
+        self.do_symlink = None
+        self.extra_files = []
+
+        # initialize the create_init_module flag from the global
+        # determined at runtime
+        self.create_init_module = create_init_module
+        self.init_module_dir = None
+        install.initialize_options(self)
+
+    def finalize_options(self):
+        if self.do_symlink is None:
+            if os.name == "posix":
+                self.do_symlink = 1
+            else:
+                self.do_symlink = 0
+        install.finalize_options(self)
+        self.expand_with_pure_python_dirs(["init_module_dir"])
+
+    def expand_with_pure_python_dirs(self, attrs):
+        """Expand the attributes with default values of base and platbase"""
+        # it seems that the values for "prefix" and "exec_prefix" in
+        # self.config_vars are the corresponding values used by the
+        # python interpreter, so we just assign these to "base" and
+        # "platbase".
+        config_vars = self.config_vars.copy()
+        config_vars["base"] = self.config_vars["prefix"]
+        config_vars["platbase"] = self.config_vars["exec_prefix"]
+        for attr in attrs:
+            val = getattr(self, attr)
+            if val is not None:
+                if os.name == 'posix':
+                    val = os.path.expanduser(val)
+                val = subst_vars(val, config_vars)
+                setattr(self, attr, val)
+
+    def select_scheme(self, scheme):
+        """Extend the inherited method to set init_module_dir"""
+        install.select_scheme(self, scheme)
+        # only set init_module_dir if it wasn't set by the user
+        if self.init_module_dir is None:
+            self.init_module_dir = INSTALL_SCHEMES[scheme]['purelib']
+
+    def convert_paths(self, *args):
+        """Extend the inherited method so that we can remember some filename
+        """
+        # remember the installation directory before its root gets
+        # changed
+        self.install_lib_orig = self.install_lib
+        apply(install.convert_paths, (self,) + args)
+
+    def run(self):
+        install.run(self)
+        for item in self.extra_files:
+            if type(item) == TupleType:
+                src, dest = item
+            else:
+                src = dest = item
+            self.copy_file(convert_path(src),
+                           os.path.join(self.root, convert_path(dest)))
+
+        if os.name == "posix" and self.do_symlink:
+            install_scripts = self.install_scripts
+            if self.root:
+                install_scripts = install_scripts[len(self.root):]
+            scriptfile = os.path.join(install_scripts, "thuban.py")
+            bindir = os.path.join(self.prefix, "bin")
+            if self.root:
+                bindir = change_root(self.root, bindir)
+            binfile = os.path.join(bindir, "thuban")
+            self.mkpath(bindir)
+            self.link_file(scriptfile, binfile)
+
+        if self.create_init_module:
+            # create the init module
+            initfilename = self.thuban_init_filename()
+            if self.root:
+                initfilename = change_root(self.root, initfilename)
+            contents = thubaninit_contents(self.install_lib_orig)
+            self.mkpath(os.path.dirname(initfilename))
+            self.execute(write_file, (initfilename, contents),
+                         "Create %s" % initfilename)
+
+    def link_file(self, src, dest):
+        """Create a symbolic link dest pointing to src.
+
+        Unlike the symlink variant of the command object's copy_file
+        method, this method even performs the link if src doesn't exist.
+        This is useful when installing with an alternat root directory"""
+        if self.verbose:
+            self.announce("symlinking %s -> %s" % (src, dest))
+        if self.dry_run:
+            return
+
+        if not os.path.exists(dest):
+            os.symlink(src, dest)
+
+    def thuban_init_filename(self):
+        """Return the filename for the init-module"""
+        # Since we override the normal install dirs to point to our own
+        # prefix we have to reach into installed
+        return self.init_module_dir + "/thubaninit.py"
+
+    def get_outputs (self):
+        outputs = install.get_outputs(self)
+        for item in self.extra_files:
+            if type(item) == TupleType:
+                src, dest = item
+            else:
+                src = dest = item
+            outputs.append(os.path.join(self.root, convert_path(dest)))
+        if os.name == "posix" and self.do_symlink:
+            bindir = os.path.join(self.prefix, "bin")
+            if self.root:
+                bindir = change_root(self.root, bindir)
+            binfile = os.path.join(bindir, "thuban")
+            outputs.append(binfile)
+        if self.create_init_module:
+            initfilename = self.thuban_init_filename()
+            if self.root:
+                initfilename = change_root(self.root, initfilename)
+            outputs.append(initfilename)
+        return outputs
+
+
+# scripts to override some of the commands put into the spec-file by the
+# bdist_rpm command.
+
+bdist_rpm_prep_script = '''
+%setup
+cp libraries/pyshapelib/{README,README.pyshapelib}
+cp libraries/pyshapelib/{COPYING,COPYING.pyshapelib}
+cp libraries/pyprojection/{LICENSE,LICENSE.pyprojection}
+'''
+
+bdist_rpm_build_script = '''
+env PATH="$PATH:%(prefix)s/lib/wxPython/bin:/usr/lib/wxPython/bin" CFLAGS="$RPM_OPT_FLAGS" %(python)s setup.py build
+'''
+
+bdist_rpm_install_script = '''
+%(python)s setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES \
+   --prefix=%(prefix)s
+'''
+
+
+class thuban_bdist_rpm(bdist_rpm):
+
+    """Thuban specific RPM distribution command"""
+
+    user_options = bdist_rpm.user_options[:]
+    user_options.extend([("prefix=", None, "Install prefix for the RPM"),
+                         ])
+
+    def initialize_options(self):
+        # per default, RPMs are installed in /usr
+        self.prefix = "/usr/"
+
+        # create the scripts we want to override. We actually fill them
+        # with contents later because some values we put into those
+        # scripts such as the python interpreter to use are only known
+        # then.
+        open("bdist_rpm_prep", "w").close()
+        open("bdist_rpm_build", "w").close()
+        open("bdist_rpm_install", "w").close()
+        bdist_rpm.initialize_options(self)
+
+    def _make_spec_file(self):
+        # create the scripts for the spec-file. Now we know the python
+        # interpreter to use.
+        open("bdist_rpm_prep", "w").write(bdist_rpm_prep_script)
+
+        build = bdist_rpm_build_script % {"python": self.python,
+                                          "prefix": self.prefix}
+        open("bdist_rpm_build", "w").write(build)
+
+        install = bdist_rpm_install_script % {"python": self.python,
+                                              "prefix": self.prefix}
+        open("bdist_rpm_install", "w").write(install)
+
+        #
+        return bdist_rpm._make_spec_file(self)
+
+
+class bdist_inno(Command):
+
+    """Command to create a windows installer with Inno Setup"""
+
+    description = "Create a windows installer with Inno Setup"
+
+    user_options = [
+        ('skip-build', None, "skip the build steps"),
+        ('bdist-dir=', None,
+         "temporary directory for creating the distribution"),
+        ('run-inno', None,
+         "Run inno-setup to create the installer. On by default on nt"),
+        ('iss-name', None,
+         "The name of the iss file to generate. "
+         "Shouldn't contain directories"),
+
+        # Parameters for the Inno Setup script
+        ('copyright', None, "Copyright notice for the Inno Setup file"),
+        ('default-dir-name', None,
+         "Default installation directory. Defaults to '{pf}\\<name>'"),
+        ('default-group-name', None,
+         "Default program group name. Defaults to <name>'"),
+        ("license-file", None, "File containing the license."),
+        ("output-basename", None,
+         "Base filename for the Inno Setup output "
+         "(defaults to <name>-<version>-<issrevision>)."),
+        ("iss-revision", None,
+         "revision of the generated installer of the package version"),
+
+        ("icons-entries", None,
+         "List if InnoIconItems "
+         "(this can only be set from inside the setup.py script)"),
+        ]
+
+    boolean_options = ["do-symlink"]
+
+    def initialize_options(self):
+        self.skip_build = 0
+        self.bdist_dir = None
+        self.run_inno = None
+        self.iss_name = None
+        self.copyright = ""
+        self.default_dir_name = None
+        self.default_group_name = None
+        self.license_file = None
+        self.output_basename = None
+        self.iss_revision = None
+        self.icons_entries = []
+
+    def finalize_options(self):
+        self.set_undefined_options("install",
+                                   ('skip_build', 'skip_build'))
+        if self.bdist_dir is None:
+            bdist_base = self.get_finalized_command('bdist').bdist_base
+            self.bdist_dir = os.path.join(bdist_base, 'inno')
+
+        if self.run_inno is None:
+            self.run_inno = os.name == "nt"
+
+        name = self.distribution.get_name()
+        if self.iss_name is None:
+            self.iss_name = name + '.iss'
+
+        if self.default_dir_name is None:
+            self.default_dir_name = "{pf}\\" + name
+        if self.default_group_name is None:
+            self.default_group_name = name
+
+        if self.iss_revision is None:
+            self.iss_revision = 0
+        if self.output_basename is None:
+            self.output_basename = "%s-%s-%d" \
+                                   % (name, self.distribution.get_version(),
+                                      int(self.iss_revision))
+
+    def run(self, install_options = None):
+        """Execute the command. install_options if given, should be a
+        directory of additional options to set in the install step"""
+        # Obviously have to build before we can install
+
+        # add gdal to the build
+	for (dirpath, dnames, fnames) in os.walk('gdal'):			
+		files_in_dir = []
+		dp = '/'.join(dirpath.split('\\'))
+		for f in fnames:
+			if os.path.isfile(os.path.join(dirpath,f)):			
+				files_in_dir.append( dp + '/' + f)		
+		if len(files_in_dir) > 0:
+			data_files.append(( dp , files_in_dir))
+        # add thubaninit to the build
+
+
+        if not self.skip_build:
+            self.run_command('build')
+
+        # Install in a temporary directory
+        install = self.reinitialize_command('install')
+        install.root = self.bdist_dir
+        if install_options is not None:
+            for key, value in install_options.items():
+                setattr(install, key, value)
+        if os.name != 'nt':
+            # Must force install to use the 'nt' scheme;
+            install.select_scheme('nt')
+
+        self.announce("installing to %s" % self.bdist_dir)
+        install.ensure_finalized()
+        install.run()
+
+        # Create the iss file
+        iss_file = os.path.join(self.bdist_dir, self.iss_name)
+        self.execute(write_file, (iss_file, self.generate_iss()),
+                     "Create Inno Setup script file %s" % iss_file)
+
+        # and invoke
+        if self.run_inno:
+            self.spawn(["iscc", iss_file])
+
+    def generate_iss(self):
+        """Return the contents of the iss file as list of strings, one
+        string per line"""
+
+        # first, turn the icons entries into a more usable form
+        icons = {}
+        for item in self.icons_entries:
+            icons[item.filename] = item
+
+        iss = []
+
+        name = self.distribution.get_name()
+        iss.extend(["[Setup]",
+                    "AppName=" + name,
+                    "AppVerName=" + name + " "+self.distribution.get_version(),
+                    "DefaultDirName=" + self.default_dir_name,
+                    "DefaultGroupName=" + self.default_group_name,
+                    ])
+        if self.copyright:
+            iss.append("AppCopyright=" + self.copyright)
+        if self.license_file:
+            iss.append("LicenseFile=" + self.license_file)
+
+        iss.append("OutputBasefilename=" + self.output_basename)
+
+        iss.append("")
+        iss.append("[Files]")
+
+        install = self.get_finalized_command("install")
+        install_scripts = self.get_finalized_command("install_scripts")
+        script_files = install_scripts.get_outputs()
+        prefixlen = len(self.bdist_dir) + len(os.sep)
+        for filename in install.get_outputs():
+            filename = filename[prefixlen:]
+            icon = icons.get(filename)
+            dirname = os.path.dirname(filename)
+            if os.name != "nt":
+                # change the separators to \ on non-windos systems
+                filename = string.join(string.split(filename, os.sep), "\\")
+                dirname =  string.join(string.split(dirname, os.sep), "\\")
+            line = 'Source: "%s"' % filename
+            if icon is not None:
+                # install it as defined in the icon object
+                backslash = string.rfind(icon.install_name, "\\")
+                if backslash >= 0:
+                    dirname = icon.install_name[:backslash]
+                    basename = icon.install_name[backslash + 1:]
+                else:
+                    dirname = ""
+                    basename = icon.install_name
+                line = '%s; DestDir: "%s"; DestName: "%s"' % (line, dirname,
+                                                              basename)
+            else:
+                line = line + '; DestDir: "{app}\\%s"' % (dirname)
+            iss.append(line)
+
+        iss.append("")
+        iss.append("[Icons]")
+        for icon in self.icons_entries:
+            line = 'Name: "{group}\\%s"; Filename: "%s";' \
+                   % (icon.title, icon.install_name)
+            iss.append(line)
+
+        return iss
+
+
+class InnoIconItem:
+
+    """Describe one item for the start menu for the Inno Setup installer"""
+
+    def __init__(self, filename, title, install_name = None):
+        self.filename = filename
+        self.title = title
+        if install_name is not None:
+            self.install_name = install_name
+        else:
+            self.install_name = filename
+
+
+class thuban_bdist_inno(bdist_inno):
+
+    """Thuban specific Inno Setup stuff"""
+
+    def run(self):
+        install_options = {
+            "prefix": ".",
+            "install_lib": "$base",
+            "install_data": "$base",
+            "install_scripts": "$base",
+            "warn_dir": 0,
+            "extra_files": ["COPYING", "Lib/proj.dll"],
+            }
+	install_options["extra_files"].extend(self.get_gdal_content())
+
+        # don't make a symlink because we're simulating windows, so
+        # that we can generate the iss-file even on Linux
+        install_options["do_symlink"] = 0
+
+        bdist_inno.run(self, install_options)
+
+    def get_gdal_content(self):
+        '''
+        Return the list of files in the gdal directory of the Thuban installation
+        '''
+	gdal_files = []
+	for (dirpath, dnames, fnames) in os.walk('gdal'):		    
+	    if len(fnames) > 0:
+	        for file in fnames :
+		    gdal_files.append(dirpath + os.sep + file)
+	return gdal_files
+
+class thuban_build_docs(Command):
+
+    """Command to generate documentation from source code."""
+
+    description = "Generate documentation."
+
+    user_options = []
+
+    def initialize_options(self): pass
+
+    def finalize_options(self): pass
+
+    def run(self, install_options = None):
+        self.spawn(["happydoc", "-d./Doc", "./Thuban"])
+
+class thuban_build_ext(build_ext):
+
+    """Extend the build_ext command with some Thuban specific options
+
+    --with-gdal, --without-gdal
+
+        Switch the optional GDAL support on/off.  Default is On.
+
+    --use-wx-python-swig-hack
+
+        For performance reasons, Thuban access wxPython objects at the
+        C++ level so that it can directly call wxWidgets code from C++.
+        The normal and preferred way to do that is to use the API
+        defined in wxPython.h.  Unfortunately, this header file is not
+        distributed with binary packages of wxPython on some platforms.
+        By using the --use-wx-python-swig-hack option you can activate a
+        way to access the C++ objects without wxPython.h.  This relies
+        on internals of SWIG, so it might change with future wxPython
+        versions.  Therefore, only use this option if the normal way
+        doesn't work for you.
+    """
+
+    user_options = build_ext.user_options[:]
+    user_options.extend([("with-gdal", None, "Include GDAL support."),
+                         ("without-gdal", None, "Don't include GDAL support."),
+                         ("use-wx-python-swig-hack", None,
+                 "Use a hack to access wxPython objects at the C++ level"
+                 "(use only when you absolutely can't use wxPython.h)")])
+
+    boolean_options = ["with-gdal", "use-wx-python-swig-hack"]
+    negative_opt = {'without-gdal' : 'with-gdal'}
+
+    def initialize_options(self):
+        self.with_gdal = True
+        self.use_wx_python_swig_hack = False
+        build_ext.initialize_options(self)
+
+    def finalize_options(self):
+        build_ext.finalize_options(self)
+        if self.with_gdal and include_gdal:
+            self.extensions.append(Extension("Lib.gdalwarp",
+                                [ext_dir + "/thuban/gdalwarp.cpp"],
+                                include_dirs = gdal_cs_params[CS_INCDIRS] +
+                                               [ext_dir + "/thuban/"],
+                                define_macros = gdal_cs_params[CS_DEFS],
+                                library_dirs = gdal_cs_params[CS_LIBDIRS],
+                                libraries = gdal_cs_params[CS_LIBS]))
+        if self.use_wx_python_swig_hack:
+            wxproj_extension.define_macros.append(("USE_WX_PYTHON_SWIG_HACK",
+                                                   None))
+
+    def run(self, install_options = None):
+        build_ext.run(self)
+
+#
+#   Run the script
+#
+
+long_description = """\
+Thuban is a viewer for geographic data written in Python
+"""
+
+setup(name = "Thuban",
+      version = "1.2.0",
+      description = "Geographic data viewer",
+      long_description = long_description,
+      license = "GPL",
+      author = "Intevation GmbH",
+      author_email = "thuban at intevation.de",
+      url = "http://thuban.intevation.de/",
+
+      scripts = ["thuban.py"],
+      packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI",
+                  "Extensions", "Extensions.gns2shp", "Extensions.wms",
+                  "Extensions.importAPR", "Extensions.profiling", 
+		          "Extensions.svgexport", "Extensions.mouseposition", 
+		          "Extensions.bboxdump", "Extensions.ogr", 
+                  "Extensions.umn_mapserver"],
+      ext_modules = extensions,
+      py_modules = py_modules,
+      data_files = data_files,
+
+      # defaults for the install command
+      options = {"install":
+                 # prefix defaults to python's prefix normally
+                 {"prefix": prefix,
+                  # make sure both libs and scripts are installed in the
+                  # same directory.
+                  "install_lib": "$base/lib/thuban",
+                  "install_scripts": "$base/lib/thuban",
+                  "install_data": "$base/lib/thuban",
+                  # Don't print warning messages about the lib dir not
+                  # being on Python's path. The libraries are Thuban
+                  # specific and are installed just for Thuban. They'll
+                  # be automatically on Python's path when Thuban is run
+                  "warn_dir": 0,
+                  },
+                 "bdist_inno":
+                 {"icons_entries": [InnoIconItem(".\\thuban.py",
+                                                 "Start Thuban",
+                                                 "{app}\\thuban.pyw")],
+                  "license_file": "COPYING",
+                  }
+                 },
+      cmdclass = {"build_py": thuban_build_py,
+                  "install_local": InstallLocal,
+                  "install": ThubanInstall,
+                  "bdist_rpm": thuban_bdist_rpm,
+                  "bdist_inno": thuban_bdist_inno,
+                  "data_dist": data_dist,
+                  "build_docs": thuban_build_docs,
+                  "build_ext": thuban_build_ext
+                  })
+
+

Added: packages/thuban/branches/upstream/current/test/README
===================================================================
--- packages/thuban/branches/upstream/current/test/README	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/README	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,41 @@
+This directory contains the Thuban test suite.
+
+To run all tests run runtests.py:
+
+   $ python runtests.py
+
+To run individual tests, run one of the test_*.py scripts, e.g.:
+
+   $ python test_table.py -v
+
+
+The tests use the unittest module of the python standard library.
+
+Some of the tests expect the iceland sample data to be present in
+../Data and so may fail if you are working from a source archive
+unless you also add the data.
+
+Test for optional features should be automatically skipped when run on
+an installation where the feature is not available or the test can't be
+run for some other reason as may be the case with the postgis interface
+tests (see below). Skipped tests are marked with an S in the default
+brief output and are listed after all test have been run.
+
+The PostGIS tests require a PostGIS installation on the machine where
+the tests are run even though Thuban can use PostGIS database as long as
+psycopg is installed. The test will create their own database cluster in
+temp/postgis and start their own postmaster process, so the only
+requirement is that the software is installed and the various postgresql
+command line programs are on the PATH because they're executed as
+subprocesses to build the database cluster, start the postmaster, etc.
+
+E.g. Debian 4.0 (Etch) can have several PostGIS installations
+in parallel. So you can give the PATH to the one you want to test
+on the command line:
+
+    $ PATH=$PATH:/usr/lib/postgresql/8.1/bin/ python runtests.py
+
+
+$Revision: 2723 $
+$Source$
+$Id: README 2723 2007-02-20 10:22:54Z bernhard $

Added: packages/thuban/branches/upstream/current/test/localessupport.py
===================================================================
--- packages/thuban/branches/upstream/current/test/localessupport.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/localessupport.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,61 @@
+# Copyright (C) 2006 by Intevation GmbH
+# Author(s):
+# Bernhard Reiter <bernhard at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Support code for setting locales."""
+
+__version__ = "$Revision: $"
+# $Id: xmlsupport.py 1683 2003-08-28 15:20:57Z bh $
+
+import locale
+from locale import LC_NUMERIC, getlocale, setlocale, localeconv
+
+_verbose = 0
+
+def setdecimalcommalocale():
+    """Find and set LC_NUMERIC locale that uses comma as decimal_point.
+
+    Return the previous locale to be able to set the previous LC_NUMERIC.
+    This can be "(None, None)" or None if none was found.
+    """
+
+    encodings = [".UTF-8", "@euro"]
+    locales = ["de_DE", "fr_FR", "fr_BE"]
+
+    oldlocale = getlocale(LC_NUMERIC)
+
+    tries = []
+    for l in locales:
+        for e in encodings:
+            tries.append(l + e)
+
+    for t in tries:
+        try:
+            if _verbose > 0:
+                print "trying", repr(t)
+            setlocale(LC_NUMERIC,t)
+        except locale.Error:
+            continue
+        break
+
+    # did we find one?
+    if localeconv()['decimal_point'] == ",":
+        return oldlocale
+
+    setlocale(LC_NUMERIC,oldlocale)
+    return None
+
+if __name__ == "__main__":
+    # test and print result
+    print "Searching for LC_NUMERIC locale with comma as decimal_point ..."
+    _verbose = 1
+    oldlocale = setdecimalcommalocale()
+    if oldlocale == None:
+        print "none found."
+    else:
+        print "found: ",
+        print getlocale(LC_NUMERIC)
+        setlocale(LC_NUMERIC,oldlocale)

Added: packages/thuban/branches/upstream/current/test/mockgeo.py
===================================================================
--- packages/thuban/branches/upstream/current/test/mockgeo.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/mockgeo.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,152 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Mock geometric/geographic objects"""
+
+from __future__ import generators
+
+__version__ = "$Revision: 1593 $"
+# $Source$
+# $Id: mockgeo.py 1593 2003-08-15 14:10:27Z bh $
+
+
+class SimpleShape:
+
+    def __init__(self, shapeid, points):
+        self.shapeid = shapeid
+        self.points = points
+
+    def Points(self):
+        return self.points
+
+    def ShapeID(self):
+        return self.shapeid
+
+    def RawData(self):
+        return self.points
+
+    def compute_bbox(self):
+        xs = []
+        ys = []
+        for part in self.Points():
+            for x, y in part:
+                xs.append(x)
+                ys.append(y)
+        return (min(xs), min(ys), max(xs), max(ys))
+
+
+class SimpleShapeStore:
+
+    """A simple shapestore object which holds its data in memory"""
+
+    def __init__(self, shapetype, shapes, table):
+        """Initialize the simple shapestore object.
+
+        The shapetype should be one of the predefined SHAPETYPE_*
+        constants. shapes is a list of shape definitions. Each
+        definitions is a list of lists of tuples as returned by the
+        Shape's Points() method. The table argument should be an object
+        implementing the table interface and contain with one row for
+        each shape.
+        """
+        self.shapetype = shapetype
+        self.shapes = shapes
+        self.table = table
+        assert table.NumRows() == len(shapes)
+
+    def ShapeType(self):
+        return self.shapetype
+
+    def Table(self):
+        return self.table
+
+    def NumShapes(self):
+        return len(self.shapes)
+
+    def Shape(self, index):
+        return SimpleShape(index, self.shapes[index])
+
+    def BoundingBox(self):
+        xs = []
+        ys = []
+        for shape in self.shapes:
+            for part in shape:
+                for x, y in part:
+                    xs.append(x)
+                    ys.append(y)
+        return (min(xs), min(ys), max(xs), max(ys))
+
+    def ShapesInRegion(self, bbox):
+        left, bottom, right, top = bbox
+        if left > right:
+            left, right = right, left
+        if bottom > top:
+            bottom, top = top, bottom
+        for i in xrange(len(self.shapes)):
+            shape = SimpleShape(i, self.shapes[i])
+            sleft, sbottom, sright, stop = shape.compute_bbox()
+            if (left <= sright and right >= sleft
+                and top >= sbottom and bottom <= stop):
+                yield shape
+
+    def AllShapes(self):
+        for i in xrange(len(self.shapes)):
+            yield SimpleShape(i, self.shapes[i])
+
+
+class AffineProjection:
+
+    """Projection-like object implemented with an affine transformation
+
+    The transformation matrix is defined by a list of six floats:
+
+           [m11, m21, m12, m22, v1, v2]
+
+    This list is essentially in the same form as used in PostScript.
+
+    This interpreted as the following transformation of (x, y):
+
+            / x \   / m11 m12 \ / x \   / v1 \
+        T * |   | = |         | |   | + |    |
+            \ y /   \ m21 m22 / \ y /   \ v2 /
+
+    or, in homogeneous coordinates:
+
+                     / m11 m12 v1 \ / x \
+                     |            | |   |
+                  ^= | m21 m22 v2 | | y |
+                     |            | |   |
+                     \ 0   0   1  / \ 1 /
+
+    Obviously this is not a real geographic projection, but it's useful
+    in test cases because it's simple and the result is easily computed
+    in advance.
+    """
+
+    def __init__(self, coeff):
+        self.coeff = coeff
+
+        # determine the inverse transformation right away. We trust that
+        # an inverse exist for the transformations used in the Thuban
+        # test suite.
+        m11, m21, m12, m22, v1, v2 = coeff
+        det = float(m11 * m22 - m12 * m21)
+        n11 = m22 / det
+        n12 = -m12 / det
+        n21 = -m21 / det
+        n22 = m11 / det
+        self.inv = [n11, n21, n12, n22, -n11*v1 - n12*v2, -n21*v1 - n22*v2]
+
+    def _apply(self, matrix, x, y):
+        m11, m21, m12, m22, v1, v2 = matrix
+        return (m11 * x + m12 * y + v1), (m21 * x + m22 * y + v2)
+
+    def Forward(self, x, y):
+        return self._apply(self.coeff, x, y)
+
+    def Inverse(self, x, y):
+        return self._apply(self.inv, x, y)

Added: packages/thuban/branches/upstream/current/test/postgissupport.py
===================================================================
--- packages/thuban/branches/upstream/current/test/postgissupport.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/postgissupport.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,788 @@
+# Copyright (C) 2003, 2004, 2005, 2006 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Support module for tests that use a live PostGIS database"""
+
+__version__ = "$Revision: 2717 $"
+# $Source$
+# $Id: postgissupport.py 2717 2007-01-01 21:44:05Z bernhard $
+
+import sys
+import os
+import time
+import popen2
+import shutil
+import traceback
+import re
+
+import support
+
+try:
+    import psycopg
+except ImportError:
+    psycopg = None
+
+#
+#       Helper code
+#
+
+def run_config_script(cmdline):
+    """Run command cmdline and return its stdout or none in case of errors"""
+    pipe = os.popen(cmdline)
+    result = pipe.read()
+    if pipe.close() is not None:
+        raise RuntimeError('Command %r failed' % cmdline)
+    return result
+
+def run_command(command, outfilename = None):
+    """Run command as a subprocess and send its stdout and stderr to outfile
+
+    The subprocess is run synchroneously so the function returns once
+    the subprocess has termninated. If the process' exit code is not
+    zero raise a RuntimeError.
+
+    If outfilename is None stdout and stderr are still captured but they
+    are ignored and not written to any file.
+    """
+    proc = popen2.Popen4(command)
+    proc.tochild.close()
+    output = proc.fromchild.read()
+    status = proc.wait()
+    if outfilename is not None:
+        outfile = open(outfilename, "w")
+        outfile.write(output)
+        outfile.close()
+    if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0:
+        if outfilename:
+            message = "see %s" % outfilename
+        else:
+            message = output
+        raise RuntimeError("command %r exited with code %d.\n%s"
+                           % (command, status, message))
+
+
+def run_boolean_command(command):
+    """
+    Run command as a subprocess silently and return whether it ran successfully
+
+    Silently means that all output is captured and ignored. The exit
+    status is true if the command ran successfull, i.e. it terminated by
+    exiting and returned as zero exit code and false other wise
+    """
+    try:
+        run_command(command, None)
+        return 1
+    except RuntimeError:
+        pass
+    return 0
+
+
+#
+#       PostgreSQL and database
+#
+
+_pg_ctl_command = "pg_ctl"
+_initdb_command = "initdb"
+# Example Values for Debian (upcomind Etch) postgresql-8.1 
+# TODO: detect which values to use here.
+#_pg_ctl_command = "/usr/lib/postgresql/8.1/bin/pg_ctl"
+#_initdb_command = "/usr/lib/postgresql/8.1/bin/initdb"
+
+class PostgreSQLServer:
+
+    """A PostgreSQL server
+
+    Instances of this class represent a PostgreSQL server with postgis
+    extensions run explicitly for the test cases. Such a server has its
+    own database directory and its own directory for the unix sockets so
+    that it doesn't interfere with any other PostgreSQL server already
+    running on the system.
+    """
+
+    def __init__(self, dbdir, port, postgis_sql, socket_dir):
+        """Initialize the PostgreSQLServer object
+
+        Parameters:
+
+          dbdir -- The directory for the databases
+          port -- The port to use
+          postgis_sql -- The name of the file with the SQL statements to
+                         initialize a database for postgis.
+          socket_dir -- The directory for the socket files.
+
+        When connecting to the database server use the port and host
+        instance variables.
+        """
+        self.dbdir = dbdir
+        self.port = port
+        self.postgis_sql = postgis_sql
+        self.socket_dir = socket_dir
+
+        # For the client side the socket directory can be used as the
+        # host if the name starts with a slash.
+        self.host = os.path.abspath(socket_dir)
+
+        # name and password for the admin and an unprivileged user
+        self.admin_name = "postgres"
+        self.admin_password = "postgres"
+        self.user_name = "observer"
+        self.user_password = "telescope"
+
+        # Map db names to db objects
+        self.known_dbs = {}
+
+    def createdb(self):
+        """Create the database in dbdir and start the server.
+
+        First check whether the dbdir already exists and if necessary
+        stop an already running postmaster and remove the dbdir
+        directory completely. Then create a new database cluster in the
+        dbdir and start a postmaster.
+        """
+        if os.path.isdir(self.dbdir):
+            if self.is_running():
+                self.shutdown()
+            shutil.rmtree(self.dbdir)
+        os.mkdir(self.dbdir)
+
+        run_command([_initdb_command, "-D", self.dbdir, "-U", self.admin_name],
+                    os.path.join(self.dbdir, "initdb.log"))
+
+        extra_opts = "-p %d" % self.port
+        if self.socket_dir is not None:
+            extra_opts += " -k %s" % self.socket_dir
+        run_command([_pg_ctl_command, "-D", self.dbdir,
+                     "-l", os.path.join(self.dbdir, "logfile"),
+                     "-o", extra_opts, "start"],
+                    os.path.join(self.dbdir, "pg_ctl-start.log"))
+        # the -w option of pg_ctl doesn't work properly when the port is
+        # not the default port, so we have to implement waiting for the
+        # server ourselves
+        self.wait_for_postmaster()
+
+        self.alter_user(self.admin_name, self.admin_password)
+        self.create_user(self.user_name, self.user_password)
+
+    def wait_for_postmaster(self):
+        """Return when the database server is running
+
+        Internal method to wait until the postmaster process has been
+        started and is ready for client connections.
+        """
+        max_count = 60
+        count = 0
+        while count < max_count:
+            try:
+                run_command(["psql", "-l", "-p", str(self.port),
+                             "-h", self.host, "-U", self.admin_name],
+                            os.path.join(self.dbdir, "psql-%d.log" % count))
+            except RuntimeError:
+                pass
+            except:
+                traceback.print_exc()
+            else:
+                break
+            time.sleep(0.5)
+            count += 1
+        else:
+            raise RuntimeError("postmaster didn't start")
+
+    def is_running(self):
+        """Return whether a postmaster process is running on self.dbdir
+
+        This method runs pg_ctl status on the dbdir and returns True if
+        that command succeeds and False otherwise.
+
+        Note that it is possible that this method returns true even if
+        the PostgreSQLServer instance has just been created and
+        createdb() has not been called yet.  This can happen, for
+        instance, if the server has been started manually for debugging
+        purposes after a test suite run.
+        """
+        return run_boolean_command([_pg_ctl_command, "-D", self.dbdir, "status"])
+
+    def shutdown(self):
+        """Stop the postmaster running for self.dbdir"""
+        run_command([_pg_ctl_command, "-m", "fast", "-D", self.dbdir, "stop"],
+                    os.path.join(self.dbdir, "pg_ctl-stop.log"))
+
+    def new_postgis_db(self, dbname, tables = None, reference_systems = None,
+                       views = None):
+        """Create and return a new PostGISDatabase object using self as server
+        """
+        db = PostGISDatabase(self, self.postgis_sql, dbname, tables = tables,
+                             reference_systems = reference_systems,
+                             views = views)
+        db.initdb()
+        self.known_dbs[dbname] = db
+        return db
+
+    def get_static_data_db(self, dbname, tables, reference_systems, views):
+        """Return a PostGISDatabase for a database with the given static data
+
+        If no databasse of the name dbname exists, create a new one via
+        new_postgis_db and upload the data.
+
+        If a database of the name dbname already exists and uses the
+        indicated data, return that. If the already existing db uses
+        different data raise a value error.
+
+        If the database doesn't exist, create a new one via
+        self.new_postgis_db.
+
+        The parameters tables and reference_systems have the same
+        meaning as for new_postgis_db.
+        """
+        db = self.known_dbs.get(dbname)
+        if db is not None:
+            if db.has_data(tables, reference_systems, views):
+                return db
+            raise ValueError("PostGISDatabase named %r doesn't have tables %r"
+                             % (dbname, tables))
+        return self.new_postgis_db(dbname, tables, reference_systems, views)
+
+    def get_default_static_data_db(self):
+        dbname = "PostGISStaticTests"
+        srids = [(1, "proj=longlat datum=WGS84")]
+        tables = [
+            # Direct copies of the shapefiles. The shapeids are exactly
+            # the same, except where changed with "gid_offset", of
+            # course.  Note that the test implementation requires that
+            # all the landmard tables use an gid_offset of 1000.
+            ("landmarks", os.path.join("..", "Data", "iceland",
+                                       "cultural_landmark-point.shp"),
+             [("gid_offset", 1000)]),
+            ("political", os.path.join("..", "Data", "iceland",
+                                             "political.shp")),
+            ("roads_multi", os.path.join("..", "Data", "iceland",
+                                         "roads-line.shp")),
+
+            # same as roads-multi but using LINESTRING instead of
+            # MULTILINESTRING
+            ("roads", os.path.join("..", "Data", "iceland",
+                                         "roads-line.shp"),
+             [("force_wkt_type", "LINESTRING")]),
+
+            # The polygon data as a MULTIPOLYGON geometry type
+            ("political_multi", os.path.join("..", "Data", "iceland",
+                                             "political.shp"),
+             [("force_wkt_type", "MULTIPOLYGON")]),
+
+            # Copy of landmarks but using an srid != -1
+            ("landmarks_srid", os.path.join("..", "Data", "iceland",
+                                       "cultural_landmark-point.shp"),
+             [("gid_offset", 1000),
+              ("srid", 1)]),
+
+            # Copy of landmarks with a gid column called "point_id" instead
+            # of "gid" and using an srid != -1.
+            ("landmarks_point_id", os.path.join("..", "Data", "iceland",
+                                                "cultural_landmark-point.shp"),
+             [("gid_offset", 1000),
+              ("srid", 1),
+              ("gid_column", "point_id")]),
+            ]
+        views = [("v_landmarks", "SELECT * FROM landmarks_point_id")]
+        return self.get_static_data_db(dbname, tables, srids, views)
+
+    def connection_params(self, user):
+        """Return the connection parameters for the given user
+
+        The return value is a dictionary suitable as keyword argument
+        list to PostGISConnection. The user parameter may be either
+        'admin' to connect as admin or 'user' to connect as an
+        unprivileged user.
+        """
+        return {"host": self.host, "port": self.port,
+                "user": getattr(self, user + "_name"),
+                "password": getattr(self, user + "_password")}
+
+    def connection_string(self, user):
+        """Return (part of) the connection string to pass to psycopg.connect
+
+        The string contains host, port, user and password. The user
+        parameter must be either 'admin' or 'user', as for
+        connection_params.
+        """
+        params = []
+        for key, value in self.connection_params(user).items():
+            # FIXME: this doesn't do quiting correctly but that
+            # shouldn't be much of a problem (people shouldn't be using
+            # single quotes in filenames anyway :) )
+            params.append("%s='%s'" % (key, value))
+        return " ".join(params)
+
+    def execute_sql(self, dbname, user, sql):
+        """Execute the sql statament and return a result for SELECT statements
+
+        The user parameter us used as in connection_params. The dbname
+        parameter must be the name of a database in the cluster.  The
+        sql parameter is the SQL statement to execute as a string.  If
+        the string starts with 'select' (matched case insensitively) the
+        first row of the result will be returned.  Otherwise the return
+        value is None.
+        """
+        conn = psycopg.connect("dbname=%s " % dbname
+                               + self.connection_string(user))
+        cursor = conn.cursor()
+        cursor.execute(sql)
+        if sql.lower().startswith("select"):
+            row = cursor.fetchone()
+        else:
+            row = None
+        conn.commit()
+        conn.close()
+        return row
+
+    def server_version(self):
+        """Return the server version as a tuple (major, minor, patch)
+
+        Each item in the tuple is an int.
+        """
+        result = self.execute_sql("template1", "admin", "SELECT version();")[0]
+        match = re.match(r"PostgreSQL (\d+\.\d+\.\d+)", result)
+        if match:
+            return tuple(map(int, match.group(1).split(".")))
+        else:
+            raise RutimeError("Cannot determine PostgreSQL server version"
+                              " from %r" % result)
+
+    def require_authentication(self, required):
+        """Switch authentication requirements on or off
+
+        When started for the first time no passwords are required. Some
+        tests want to explicitly test whether Thuban's password
+        infrastructure works and switch password authentication on
+        explicitly. When switching it on, there should be a
+        corresponding call to switch it off again in the test case'
+        tearDown method or in a finally: block.
+        """
+        # Starting with PostgreSQL 7.3 the pg_hba.conf file has an
+        # additional column with a username.  Query the server version
+        # and generate a file in the correct format.
+        if self.server_version() >= (7, 3):
+            user = "all"
+        else:
+            user = ""
+        if required:
+            contents = "local all %s password\n" % user
+        else:
+            contents = "local all %s trust\n" % user
+        f = open(os.path.join(self.dbdir, "pg_hba.conf"), "w")
+        f.write(contents)
+        f.close()
+        run_command([_pg_ctl_command, "-D", self.dbdir, "reload"],
+                    os.path.join(self.dbdir, "pg_ctl-reload.log"))
+
+
+    def create_user(self, username, password):
+        """Create user username with password in the database"""
+        self.execute_sql("template1", "admin",
+                         "CREATE USER %s PASSWORD '%s';" % (username,password))
+
+    def alter_user(self, username, password):
+        """Change the user username's password in the database"""
+        self.execute_sql("template1", "admin",
+                         "ALTER USER %s PASSWORD '%s';" % (username,password))
+
+
+class PostGISDatabase:
+
+    """A PostGIS database in a PostgreSQLServer"""
+
+    def __init__(self, server, postgis_sql, dbname, tables = None,
+                 reference_systems = (), views = None):
+        """Initialize the PostGISDatabase
+
+        Parameters:
+
+            server -- The PostgreSQLServer instance containing the
+                database
+
+            postgis_sql -- Filename of the sql file with the postgis
+                initialization code
+
+            dbname -- The name of the database
+
+            tables -- Optional description of tables to create in the
+                new database. If given it should be a list of
+                (tablename, shapefilename) pairs meaning that a table
+                tablename will be created with the contents of the given
+                shapefile or (tablename, shapefilename, extraargs)
+                triples. The extraargs should be a list of key, value
+                pairs to use as keyword arguments to upload_shapefile.
+
+            reference_systems -- Optional description of spatial
+                reference systems.  If given, it should be a sequence of
+                (srid, params) pairs where srid is the srid defined by
+                the proj4 paramter string params.  The srid can be given
+                as an extra parameter in the tables list.
+
+            views -- Optional description of views.  If given it should
+                be a list of (viewname, select_stmt) pairs where
+                viewname is the name of the view to be created and
+                select_stmt is the select statement to use as the basis.
+                The views will be created after the tables and may refer
+                to them in the select_stmt.
+        """
+        self.server = server
+        self.postgis_sql = postgis_sql
+        self.dbname = dbname
+        self.tables = tables
+        self.views = views
+        if reference_systems:
+            self.reference_systems = reference_systems
+        else:
+            # Make sure that it's a sequence we can iterate over even if
+            # the parameter's None
+            self.reference_systems = ()
+
+    def initdb(self):
+        """Remove the old db directory and create and initialize a new database
+        """
+        run_command(["createdb", "-p", str(self.server.port),
+                     "-h", self.server.host, "-U", self.server.admin_name,
+                     self.dbname],
+                    os.path.join(self.server.dbdir, "createdb.log"))
+        run_command(["createlang", "-p", str(self.server.port),
+                     "-h", self.server.host,  "-U", self.server.admin_name,
+                     "plpgsql", self.dbname],
+                    os.path.join(self.server.dbdir, "createlang.log"))
+        # for some reason psql doesn't exit with an error code if the
+        # file given as -f doesn't exist, so we check manually by trying
+        # to open it before we run psql
+        f = open(self.postgis_sql)
+        f.close()
+        del f
+        run_command(["psql", "-f", self.postgis_sql, "-d", self.dbname,
+                     "-p", str(self.server.port), "-h", self.server.host,
+                     "-U", self.server.admin_name],
+                     os.path.join(self.server.dbdir, "psql.log"))
+
+        self.server.execute_sql(self.dbname, "admin",
+                                "GRANT SELECT ON geometry_columns TO PUBLIC;")
+        self.server.execute_sql(self.dbname, "admin",
+                                "GRANT SELECT ON spatial_ref_sys TO PUBLIC;")
+
+        for srid, params in self.reference_systems:
+            self.server.execute_sql(self.dbname, "admin",
+                                    "INSERT INTO spatial_ref_sys VALUES"
+                                    " (%d, '', %d, '', '%s');"
+                                    % (srid, srid, params))
+        if self.tables is not None:
+            def unpack(item):
+                extra = {"force_wkt_type": None, "gid_offset": 0,
+                         "srid": -1}
+                if len(info) == 2:
+                    tablename, shapefile = info
+                else:
+                    tablename, shapefile, kw = info
+                    for key, val in kw:
+                        extra[key] = val
+                return tablename, shapefile, extra
+
+            for info in self.tables:
+                tablename, shapefile, kw = unpack(info)
+                upload_shapefile(shapefile, self, tablename, **kw)
+
+        if self.views is not None:
+            for viewname, select_stmt in self.views:
+                self.server.execute_sql(self.dbname, "admin",
+                                        "CREATE VIEW %s AS %s" % (viewname,
+                                                                  select_stmt))
+                self.server.execute_sql(self.dbname, "admin",
+                                        "GRANT SELECT ON %s TO PUBLIC;"
+                                        % viewname)
+
+    def has_data(self, tables, reference_systems, views):
+        return (self.tables == tables
+                and self.reference_systems == reference_systems
+                and self.views == views)
+
+
+def find_postgis_sql():
+    """Return the name of the postgis_sql file
+
+    A postgis installation usually has the postgis_sql file in
+    PostgreSQL's $datadir (i.e. the directory where PostgreSQL keeps
+    static files, not the directory containing the databases).
+    Unfortunately there's no way to determine the name of this directory
+    with pg_config so we assume here that it's
+    $bindir/../share/postgresql/.
+
+    Furthermore, different versions of postgis place the file in
+    slightly different locations or may even use different names.  For
+    instance:
+
+      postgis 0.7.5        $datadir/contrib/postgis.sql
+      postgis 0.8.1        $datadir/postgis.sql
+      postgis 1.0.0-rc1    $datadir/lwpostgis.sql
+      postgis 1.0.0-rc4    $datadir/contrib/lwpostgis.sql
+
+    To support both versions, we look in both places and return the
+    first one found (looking under contrib first).  
+
+    Debian (umcoming Etch) can do several version of postgresql
+    and thus has changed the paths. We try one location
+    in datadir2 only for Debian Etch postgresql-8.1.
+
+    If the file is not found the return value is None.
+    """
+    bindir = run_config_script("pg_config --bindir").strip()
+    datadir = os.path.join(bindir, "..", "share", "postgresql")
+    datadir2 = os.path.join("/", "usr", "share", "postgresql-8.1-postgis")
+
+    for filename in [os.path.join(datadir, "contrib", "postgis.sql"),
+                     os.path.join(datadir, "postgis.sql"),
+                     os.path.join(datadir, "lwpostgis.sql"),
+                     os.path.join(datadir, "contrib", "lwpostgis.sql"),
+                     os.path.join(datadir2, "lwpostgis.sql") \
+                    ]:
+        if os.path.exists(filename):
+            return filename
+
+
+_postgres_server = None
+def get_test_server():
+    """Return the test database server object.
+
+    If it doesn't exist yet, create it first.
+
+    The server will use the directory postgis under the temp dir (as
+    defined by support.create_temp_dir()) for the database cluster.
+    Sockets will be created in tempdir.
+    """
+    global _postgres_server
+    if _postgres_server is None:
+        tempdir = support.create_temp_dir()
+        dbdir = os.path.join(tempdir, "postgis")
+        socket_dir = tempdir
+
+        _postgres_server = PostgreSQLServer(dbdir, 6543, find_postgis_sql(),
+                                            socket_dir = socket_dir)
+        _postgres_server.createdb()
+
+    return _postgres_server
+
+def shutdown_test_server():
+    """Shutdown the test server if it is running"""
+    global _postgres_server
+    if _postgres_server is not None:
+        _postgres_server.shutdown()
+        _postgres_server = None
+
+
+def reason_for_not_running_tests():
+    """
+    Determine whether postgis tests can be run and return a reason they can't
+
+    There's no fool-proof way to reliably determine this short of
+    actually running the tests but we try the following here:
+
+     - test whether pg_ctl --help can be run successfully
+     - test whether the postgis_sql can be opened
+       The name of the postgis_sql file is determined by find_postgis_sql()
+     - psycopg can be imported successfully.
+    """
+    # run_command currently uses Popen4 which is not available under
+    # Windows, for example.
+    if not hasattr(popen2, "Popen4"):
+        return "Can't run PostGIS test because popen2.Popen4 does not exist"
+
+    try:
+        run_command([_pg_ctl_command, "--help"], None)
+    except RuntimeError:
+        return "Can't run PostGIS tests because pg_ctl fails"
+
+    try:
+        postgis_sql = find_postgis_sql()
+    except:
+        return "Can't run PostGIS tests because postgis.sql can't be found"
+
+    try:
+        f = open(postgis_sql)
+        f.close()
+    except:
+        return "Can't run PostGIS tests because postgis.sql can't be opened"
+
+    # The test for psycopg was already done when this module was
+    # imported so we only have to check whether it was successful
+    if psycopg is None:
+        return "Can't run PostGIS tests because psycopg can't be imported"
+
+    return ""
+
+
+_cannot_run_postgis_tests = None
+def skip_if_no_postgis():
+    global _cannot_run_postgis_tests
+    if _cannot_run_postgis_tests is None:
+        _cannot_run_postgis_tests = reason_for_not_running_tests()
+    if _cannot_run_postgis_tests:
+        raise support.SkipTest(_cannot_run_postgis_tests)
+
+def skip_if_addgeometrycolumn_does_not_use_quote_ident():
+    """Skip a test if the AddGeometryColumn function doesn't use quote_ident
+
+    If the AddGeometryColumn function doesn't use quote_ident it doesn't
+    support unusual table or column names properly, that is, it will
+    fail with errors for names that contain spaces or double quotes.
+
+    The test performed by this function is a bit simplistic because it
+    only tests whether the string 'quote_ident' occurs anywhere in the
+    postgis.sql file. This will hopefully work because when this was
+    fixed in postgis CVS AddGeometryColumn was the first function to use
+    quote_ident.
+    """
+    f = file(find_postgis_sql())
+    content = f.read()
+    f.close()
+    if content.find("quote_ident") < 0:
+        raise support.SkipTest("AddGeometryColumn doesn't use quote_ident")
+
+def coords_to_point(coords):
+    """Return string with a WKT representation of the point in coords"""
+    x, y = coords[0]
+    return "POINT(%r %r)" % (x, y)
+
+def coords_to_polygon(coords):
+    """Return string with a WKT representation of the polygon in coords"""
+    poly = []
+    for ring in coords:
+        poly.append(", ".join(["%r %r" % p for p in ring]))
+    return "POLYGON((%s))" % "), (".join(poly)
+
+def coords_to_linestring(coords):
+    """Return string with a LINESTRING WKT representation of coords"""
+    if len(coords) > 1:
+        raise ValueError("A LINESTRING can only have one arc")
+    return "LINESTRING(%s)" % ", ".join(["%r %r" % p for p in coords[0]])
+
+def coords_to_multilinestring(coords):
+    """Return string with a MULTILINESTRING WKT representation of coords"""
+    poly = []
+    for ring in coords:
+        poly.append(", ".join(["%r %r" % p for p in ring]))
+    return "MULTILINESTRING((%s))" % "), (".join(poly)
+
+def coords_to_multipolygon(coords):
+    """Return string with a WKT representation of the polygon in coords"""
+    poly = []
+    for ring in coords:
+        poly.append(", ".join(["%r %r" % p for p in ring]))
+    return "MULTIPOLYGON(((%s)))" % ")), ((".join(poly)
+
+wkt_converter = {
+    "POINT": coords_to_point,
+    "LINESTRING": coords_to_linestring,
+    "MULTILINESTRING": coords_to_multilinestring,
+    "POLYGON": coords_to_polygon,
+    "MULTIPOLYGON": coords_to_multipolygon,
+    }
+
+def upload_shapefile(filename, db, tablename, force_wkt_type = None,
+                     gid_offset = 0, gid_column = "gid", srid = -1):
+    """Upload a shapefile into a new database table
+
+    Parameters:
+
+    filename -- The name of the shapefile
+
+    db -- The PostGISDatabase instance representing the database
+
+    tablename -- The name of the table to create and into which the data
+                is to be inserted
+
+    force_wkt_type -- If given and not None, this is used as the WKT
+                geometry type to use instead of the default that would
+                be chosen based on the type of the shapefile
+
+    gid_offset -- A number to add to the shapeid to get the value for
+                the gid column (default 0)
+
+    gid_column -- The name of the column with the shape ids.  Default
+                  'gid'.  If None, no gid column will be created.  The
+                  name is directly used in SQL statements, so if it
+                  contains unusualy characters the caller should provide
+                  a suitable quoted string.
+
+    srid -- The srid of the spatial references system used by the table
+            and the data
+
+    The tables will be explicitely created WITH OIDS. This has been
+    default for PostgreSQL <8.0 and some tests relied on it (end of 2006).
+    """
+    import dbflib, shapelib
+
+    # We build this map here because we need shapelib which can only be
+    # imported after support.initthuban has been called which we can't
+    # easily do in this module because it's imported by support.
+    shp_to_wkt = {
+        shapelib.SHPT_POINT: "POINT",
+        shapelib.SHPT_ARC: "MULTILINESTRING",
+        shapelib.SHPT_POLYGON: "POLYGON",
+        }
+
+    server = db.server
+    dbname = db.dbname
+    conn = psycopg.connect("dbname=%s " % dbname
+                           + db.server.connection_string("admin"))
+    cursor = conn.cursor()
+
+    shp = shapelib.ShapeFile(filename)
+    dbf = dbflib.DBFFile(filename)
+    typemap = {dbflib.FTString: "VARCHAR",
+               dbflib.FTInteger: "INTEGER",
+               dbflib.FTDouble: "DOUBLE PRECISION"}
+
+    insert_formats = []
+    if gid_column:
+        insert_formats.append("%(gid)s")
+
+    fields = []
+    fields_decl = []
+    if gid_column:
+        fields.append(gid_column)
+        fields_decl.append("%s INT" % gid_column)
+    for i in range(dbf.field_count()):
+        ftype, name, width, prec = dbf.field_info(i)
+        fields.append(name)
+        fields_decl.append("%s %s" % (name, typemap[ftype]))
+        insert_formats.append("%%(%s)s" % name)
+    stmt = "CREATE TABLE %s (\n    %s\n) WITH OIDS ;" % (tablename,
+                                              ",\n    ".join(fields_decl))
+    cursor.execute(stmt)
+    #print stmt
+
+    numshapes, shapetype, mins, maxs = shp.info()
+    wkttype =  shp_to_wkt[shapetype]
+    if force_wkt_type:
+        wkttype = force_wkt_type
+    convert = wkt_converter[wkttype]
+
+    cursor.execute("select AddGeometryColumn('%(dbname)s',"
+                   "'%(tablename)s', 'the_geom', %(srid)d, '%(wkttype)s', 2);"
+                   % locals())
+    fields.append("the_geom")
+    insert_formats.append("GeometryFromText(%(the_geom)s, %(srid)d)")
+
+    insert = ("INSERT INTO %s (%s) VALUES (%s)"
+              % (tablename, ", ".join(fields), ", ".join(insert_formats)))
+
+    for i in range(numshapes):
+        data = dbf.read_record(i)
+        data["tablename"] = tablename
+        if gid_column:
+            data["gid"] = i + gid_offset
+        data["srid"] = srid
+        data["the_geom"] = convert(shp.read_object(i).vertices())
+        #print insert % data
+        cursor.execute(insert, data)
+
+    cursor.execute("GRANT SELECT ON %s TO PUBLIC;" % tablename)
+
+    conn.commit()

Added: packages/thuban/branches/upstream/current/test/runtests.py
===================================================================
--- packages/thuban/branches/upstream/current/test/runtests.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/runtests.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,115 @@
+# Copyright (c) 2002, 2003, 2004, 2005, 2006 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Main entry point for the Thuban test suite.
+
+Just run this file as a python script to execute all tests
+"""
+
+__version__ = "$Revision: 2705 $"
+# $Source$
+# $Id: runtests.py 2705 2006-09-24 18:55:30Z bernhard $
+
+import os
+
+# It should be possible to run the Thuban testsuite without an X
+# connection, so we remove the DISPLAY environment variable which should
+# lead to an error if the wxGTK module is imported accidentally. The
+# DISPLAY variable is not always set so we catch and ignore the KeyError
+try:
+    del os.environ["DISPLAY"]
+except KeyError:
+    pass
+
+import sys
+import warnings
+import unittest
+import getopt
+
+import support
+support.initthuban()
+import Thuban.Lib.connector
+
+def find_test_modules(dirname, package = None):
+    """Return a list the names of the test modules in the directory dirname
+
+    The return value is a list of names that can be passed to
+    unittest.defaultTestLoader.loadTestsFromNames.  Each name of the
+    list is the name of a pure python module, one for each file in
+    dirname that starts with 'test'.
+
+    The optional parameter package should be the name of the python
+    package whose directory is dirname.  If package is given all names
+    in the returned list will be prefixed with package and a dot.
+    """
+    if package:
+        prefix = package + "."
+    else:
+        prefix = ""
+
+    return [prefix + name[:-3]
+            for name in os.listdir(dirname)
+                if name[:4] == "test" and name[-3:] == ".py"]
+
+
+def main():
+    """Run all the tests in the Thuban test suite"""
+
+    # Turn Thuban's deprecation warnings into errors so they're caught
+    # by the tests
+    #
+    # Maintenance: Keep a warning filter until the backwards
+    # compatibility code is removed at which time using the old
+    # interfaces should lead to other errors anyway.
+
+    # The layer attributes table, shapetable, shapefile and filename are
+    # deprecated.
+    warnings.filterwarnings("error", "The Layer attribute.*is deprecated",
+                            DeprecationWarning)
+
+    verbosity = 1
+
+    opts, args = getopt.getopt(sys.argv[1:], 'v',
+                ['verbose', 'setdecimalcommalocale', "internal-encoding="])
+    for optchar, value in opts:
+        if optchar in ("-v", "--verbose"):
+            verbosity = 2
+        elif optchar == "--internal-encoding":
+            Thuban.set_internal_encoding(value)
+        elif optchar == "--setdecimalcommalocale":
+            import localessupport
+            oldlocale = localessupport.setdecimalcommalocale()
+            if oldlocale == None:
+                print>>sys.stderr, "Did not find a locale with comma."
+        else:
+            print>>sys.stderr, "Unknown option", optchar
+
+    # Build the list of test names.  If names were given on the command
+    # line, run exactly those.  Othwerwise build a default list of
+    # names.
+    if args:
+        names = args
+    else:
+        # All Python files starting with 'test' in the current directory
+        # and some directories in Extensions contain test cases.
+        # FIXME: It should be possible to run runtests.py even when not in
+        # the test directory
+        names = find_test_modules(".")
+        names += find_test_modules("../Extensions/svgexport/test",
+                                   "Extensions.svgexport.test")
+        names += find_test_modules("../Extensions/ogr/test",
+                                   "Extensions.ogr.test")
+    suite = unittest.defaultTestLoader.loadTestsFromNames(names)
+    runner = support.ThubanTestRunner(verbosity = verbosity)
+    result = support.execute_as_testsuite(runner.run, suite)
+
+    sys.exit(not result.wasSuccessful())
+
+
+if __name__ == "__main__":
+    main()

Added: packages/thuban/branches/upstream/current/test/support.py
===================================================================
--- packages/thuban/branches/upstream/current/test/support.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/support.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,385 @@
+# Copyright (c) 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Support classes and function for the test suite
+"""
+
+__version__ = "$Revision: 2642 $"
+# $Source$
+# $Id: support.py 2642 2005-07-01 20:49:04Z bh $
+
+import os, sys
+import unittest
+import traceback
+
+import postgissupport
+
+
+def thuban_dir():
+    """Return the directory containing the Thuban package"""
+    thisdir = os.path.dirname(__file__)
+    return os.path.join(thisdir, os.pardir)
+
+def resource_dir():
+    return os.path.join(thuban_dir(), "Resources")
+
+def add_thuban_dir_to_path():
+    """Insert the Thuban directory at the beginning of the python path.
+
+    If it's already part of the path, remove later occurrences.
+    """
+    dir = thuban_dir()
+    while 1:
+        try:
+            sys.path.remove(dir)
+        except ValueError:
+            break
+    sys.path.insert(0, dir)
+
+
+_initthuban_done = 0
+def initthuban():
+    """Initialize the interpreter for using Thuban modules
+    """
+    global _initthuban_done
+    if not _initthuban_done:
+        # Thuban uses gettext to translate some strings. Some of these
+        # strings are tested for equality in some test cases. So we
+        # unset any LANG environment setting to make sure only the
+        # untranslated messages are used.
+        try:
+            del os.environ["LANG"]
+        except KeyError:
+            pass
+        add_thuban_dir_to_path()
+        import thubaninit
+
+        # Install a dummy translation function so that importing
+        # Thuban.UI doesn't install a wx specific one for which would
+        # need to import wxPython
+        import Thuban
+        Thuban.install_translation_function(lambda s: s)
+
+        # For the time being the default encoding in the test suite is
+        # latin 1.  This is mostly for historical reasons.  Other
+        # encodings can be specified as an argument for runtests.py.
+        Thuban.set_internal_encoding("latin-1")
+
+        _initthuban_done = 1
+
+
+#
+# Special test runner and result that support skipping tests
+#
+
+class SkipTest(Exception):
+    """Exception to raise in tests that are skipped for some reason
+
+    For instance, since gdal support is optional, test cases that
+    require gdal raise this exception to indicate that they are skipped.
+    Skipped is different from failure or error in that it is expected
+    under certain circumstances.
+    """
+
+class ThubanTestResult(unittest._TextTestResult):
+
+    def __init__(self, stream, descriptions, verbosity):
+        unittest._TextTestResult.__init__(self, stream, descriptions,
+                                          verbosity)
+        self.skipped_tests = {}
+
+    def add_skipped_test(self, test, exc):
+        reason = str(exc)
+        self.skipped_tests.setdefault(reason, []).append(test)
+
+    def count_skipped(self):
+        sum = 0
+        for tests in self.skipped_tests.values():
+            sum += len(tests)
+        return sum
+
+    def addError(self, test, err):
+        """Extend inherited method to handle SkipTest exceptions specially
+        """
+        #print "addError", test, err
+        if isinstance(err[1], SkipTest):
+            self.add_skipped_test(test, err[1])
+            if self.showAll:
+                self.stream.writeln("skipped")
+            elif self.dots:
+                self.stream.write('S')
+        else:
+            unittest._TextTestResult.addError(self, test, err)
+
+    def printErrors(self):
+        if self.skipped_tests:
+            if self.dots or self.showAll:
+                self.stream.writeln()
+            self.stream.writeln("Skipped tests:")
+            for reason, tests in self.skipped_tests.items():
+                self.stream.writeln("  %s:" % reason)
+                for test in tests:
+                    self.stream.writeln("    " + test.id())
+        unittest._TextTestResult.printErrors(self)
+
+    def getDescription(self, test):
+        return test.id()
+
+
+class ThubanTestRunner(unittest.TextTestRunner):
+
+    def _makeResult(self):
+        return ThubanTestResult(self.stream, self.descriptions, self.verbosity)
+
+    def run(self, test):
+        result = unittest.TextTestRunner.run(self, test)
+        self.stream.writeln("skipped = %d" % result.count_skipped())
+        return result
+
+
+class ThubanTestProgram(unittest.TestProgram):
+
+    def runTests(self):
+        """Extend inherited method so that we use a ThubanTestRunner"""
+        self.testRunner = ThubanTestRunner(verbosity = self.verbosity)
+        unittest.TestProgram.runTests(self)
+
+
+def execute_as_testsuite(callable, *args, **kw):
+    """Call callable  with args as if it were the entry point to the test suite
+
+    Return watever callable returns.
+
+    This is a helper function for run_tests and runtests.py. Call
+    callable in a try-finally block and run some cleanup and print some
+    additional information in the finally block.
+
+    The additionaly information include:
+
+     - A list of uncollected objects (after an explicit garbage
+       collector call)
+
+     - any unsubscribed messages
+    """
+    try:
+        return callable(*args, **kw)
+    finally:
+        # This has to be in a finally clause because unittest.main()
+        # ends with a sys.exit to make sure that the process exits with
+        # an appropriate exit code
+
+        # Shutdown the postgis server if it's running
+        try:
+            postgissupport.shutdown_test_server()
+        except:
+            traceback.print_exc()
+
+        # Print additional information
+        print_additional_summary()
+
+def run_tests():
+    """Frontend for unittest.main that prints some additional debug information
+
+    After calling unittest.main, run the garbage collector and print
+    uncollected objects. Also print any un-unsubscribed messages.
+    """
+    execute_as_testsuite(ThubanTestProgram)
+
+
+def print_additional_summary():
+    """Print some additional summary information after tests have been run"""
+    print_garbage_information()
+    import xmlsupport
+    xmlsupport.print_summary_message()
+
+def print_garbage_information():
+    """Print information about things that haven't been cleaned up.
+
+    Run the garbage collector and print uncollected objects. Also print
+    any un-unsubscribed messages.
+    """
+    # this function may be called indirectly from test cases that test
+    # test support modules which do not use anything from thuban itself,
+    # so we call initthuban so that we can import the connector module
+    initthuban()
+    import gc, Thuban.Lib.connector
+    gc.collect()
+    if gc.garbage:
+        print
+        print "There are %d uncollected objects:" % len(gc.garbage)
+        print gc.garbage
+    Thuban.Lib.connector._the_connector.print_connections()
+
+#
+
+def create_temp_dir():
+    """Create a temporary directory and return its name.
+
+    The temporary directory is always called temp and is created in the
+    directory where support module is located.
+
+    If the temp directory already exists, just return the name.
+    """
+    name = os.path.abspath(os.path.join(os.path.dirname(__file__), "temp"))
+
+    # if the directory already exists, we're done
+    if os.path.isdir(name):
+        return name
+
+    # create the directory
+    os.mkdir(name)
+    return name
+
+
+class FileTestMixin:
+
+    """Mixin class for tests that use files in the temporary directory
+    """
+
+    def temp_file_name(self, basename):
+        """Return the full name of the file named basename in the temp. dir"""
+        return os.path.join(create_temp_dir(), basename)
+
+    def temp_dir(self):
+        """Return the name of the directory for the temporary files"""
+        return create_temp_dir()
+
+
+
+class FileLoadTestCase(unittest.TestCase, FileTestMixin):
+
+    """Base class for test case that test loading files.
+
+    This base class provides some common infrastructure for testing the
+    reading of files.
+
+    Each test case should be its own class derived from this one. There
+    is one file associated with each class. The contents are defined by
+    the file_contents class attribute and its name by the filename
+    method.
+
+    Derived classes usually only have to provide appropriate values for
+    the file_contents and file_extension class attributes.
+    """
+
+    file_contents = None
+    file_extension = ""
+
+    def filename(self):
+        """Return the name of the test file to use.
+
+        The default implementation simply calls self.temp_file_name with
+        a basename derived from the class name by stripping off a
+        leading 'test_' and appending self.file_extension.
+        """
+        name = self.__class__.__name__
+        if name.startswith("test_"):
+            name = name[5:]
+        return self.temp_file_name(name + self.file_extension)
+
+    def setUp(self):
+        """Create the volatile file for the test.
+
+        Write self.contents (which should be a string) to the file named
+        by self.filename().
+        """
+        filename = self.filename()
+        file = open(filename, "w")
+        file.write(self.file_contents)
+        file.close()
+
+
+class FloatComparisonMixin:
+
+    """
+    Mixin class for tests comparing floating point numbers.
+
+    This class provides a few methods for testing floating point
+    operations.
+    """
+
+    fp_epsilon = 1e-6
+    fp_inf = float('1e1000')   # FIXME: hack for infinite
+
+    def assertFloatEqual(self, test, value, epsilon = None):
+        """Assert equality of test and value with some tolerance.
+
+        Assert that the absolute difference between test and value is
+        less than self.fp_epsilon.
+        """
+        if epsilon is None:
+            epsilon = self.fp_epsilon
+        if abs(test) == self.fp_inf:
+            self.assertEqual(test, value)
+        else:
+            self.assert_(epsilon > abs(test - value),
+                     "abs(%g - %g) >= %g" % (test, value, epsilon))
+
+    def assertFloatSeqEqual(self, test, value, epsilon = None):
+        """Assert equality of the sequences test and value with some tolerance.
+
+        Assert that the absolute difference between each corresponding
+        value in test and value is less than the optional parameter
+        epsilon. If epsilon is not given use self.fp_epsilon.
+        """
+        self.assertEquals(len(test), len(value))
+        for i in range(len(test)):
+            self.assertFloatEqual(test[i], value[i], epsilon)
+
+    def assertPointListEquals(self, test, value):
+        """Assert equality of two lists of lists of tuples of float
+
+        This assertion is usually used to compare the geometry of shapes
+        as returned by a Shape object's Points() method, hence the name.
+        """
+        for i in range(len(test)):
+            self.assertEquals(len(test[i]), len(value[i]))
+            for j in range(len(test[i])):
+                self.assertFloatSeqEqual(test[i][j], value[i][j])
+
+
+class SubscriberMixin:
+
+    """Mixin class for tests for messages sent through the Connector
+
+    The SubscriberMixin has some methods that can be used as subscribers
+    of events that when called append information about the message into
+    a list of messages received.
+
+    A derived class should call the clear_messages() method in both its
+    setUp and tearDown methods to clear the list of messages received.
+    """
+
+    def clear_messages(self):
+        """Clear the list of received messages.
+
+        Call this at least in the tests setUp and tearDown methods. It's
+        important to do it in tearDown too because otherwise there may
+        be cyclic references.
+        """
+        self.received_messages = []
+
+    def subscribe_no_params(self):
+        """Method for subscriptions without parameters.
+
+        Add an empty tuple to the list of received messages.
+        """
+        self.received_messages.append(())
+
+    def subscribe_with_params(self, *args):
+        """Method for subscriptions with parameters.
+
+        Append the tuple will all arguments to this function (except for
+        the self argument) to the list of received messages.
+        """
+        self.received_messages.append(args)
+
+    def check_messages(self, messages):
+        """Check whether the messages received match the list messages"""
+        self.assertEquals(messages, self.received_messages)
+

Added: packages/thuban/branches/upstream/current/test/test_base.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_base.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_base.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,160 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the TitledObject and Modifiable
+"""
+
+__version__ = "$Revision: 1123 $"
+# $Source$
+# $Id: test_base.py 1123 2003-06-02 14:10:00Z bh $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.base import TitledObject, Modifiable
+from Thuban.Model.messages import TITLE_CHANGED, CHANGED
+
+SOMETHING_ELSE = "SOMETHING_ELSE"
+
+class SomeTitledObject(TitledObject, Modifiable):
+
+    """TitledObject for test purposes.
+
+    TitledObject is not used directly. It's a mixin to be used together
+    with Modifiable.
+    """
+
+class SomeModifiable(Modifiable):
+
+    """Modifiable for test purposes.
+
+    Modifiable is intended to be used as a base class for classes that
+    need to inform other classes when they change and that have to keep
+    track of whether they have changed. Thus we use a derived class for
+    testing that provides some methods that simulate modificatios.
+    """
+
+    def do_something(self):
+        """Call self.changed without parameters"""
+        self.changed()
+
+    def do_something_else(self):
+        """Call self.changed with a message parameter"""
+        self.changed(SOMETHING_ELSE)
+
+
+class SubscriberTest(unittest.TestCase, support.SubscriberMixin):
+
+    """Base class for test cases that use SubscriberMixin.
+
+    Just provide the default implementations of setUp and tearDown.
+    """
+
+    def setUp(self):
+        """Clear the list of received messages"""
+        self.clear_messages()
+
+    def tearDown(self):
+        """Clear the list of received messages"""
+        self.clear_messages()
+
+
+class TestTitledObject(SubscriberTest):
+
+    """Test cases for TitledObject"""
+
+    def test_titled_object(self):
+        """Test TitledObject"""
+        titled = SomeTitledObject("Some Title")
+        titled.Subscribe(TITLE_CHANGED,
+                         self.subscribe_with_params, TITLE_CHANGED)
+
+        self.assertEquals(titled.Title(), "Some Title")
+
+        titled.SetTitle("New Title")
+        self.assertEquals(titled.Title(), "New Title")
+
+        self.check_messages([(titled, TITLE_CHANGED)])
+
+
+class TestModifiable(SubscriberTest):
+
+    """Test cases for Modifiable"""
+
+    def setUp(self):
+        """Extend the inherited method to create a Modifiable instance.
+
+        Bind the Modifiable instance (actually an instance of
+        SomeModifiable) to self.modifiable and subscribe to its CHANGED
+        and SOMETHING_ELSE channels.
+        """
+        SubscriberTest.setUp(self)
+        self.modifiable = SomeModifiable()
+        self.modifiable.Subscribe(CHANGED, self.subscribe_with_params, CHANGED)
+        self.modifiable.Subscribe(SOMETHING_ELSE,
+                                  self.subscribe_with_params, SOMETHING_ELSE)
+
+    def tearDown(self):
+        """Extend the inherited method to explicitly destroy self.modifiable.
+        """
+        self.modifiable.Destroy()
+        SubscriberTest.tearDown(self)
+
+    def test_initial_state(self):
+        """Test Modifiable initial state"""
+        # initially a modifiable is unmodified
+        self.failIf(self.modifiable.WasModified())
+        # this test should not have resulted in any messages
+        self.check_messages([])
+
+    def test_silent_change(self):
+        """Test Modifiable method which doesn't issue messages"""
+        self.modifiable.do_something()
+        # Now it should be modified and we should not have received any
+        # message
+        self.assert_(self.modifiable.WasModified())
+        self.check_messages([])
+
+    def test_unset_modified(self):
+        """Test Modifiable.UnsetModified.
+
+        Test whether the UnsetModified does in fact clear the modified
+        flag and whether it issues a CHANGED message if it changes the
+        modified flag from true to false.
+        """
+        # We start with an unmodified object, so when we call
+        # UnsetModified now it shouldn't result in any message.
+        self.modifiable.UnsetModified()
+        self.check_messages([])
+        self.failIf(self.modifiable.WasModified())
+
+        # Call a method that modifies the object silently.
+        self.modifiable.do_something()
+        self.check_messages([])
+        self.assert_(self.modifiable.WasModified())
+
+        # when we now call UnsetModified it should result in a CHANGED
+        # message
+        self.modifiable.UnsetModified()
+        self.check_messages([(CHANGED,)])
+        self.failIf(self.modifiable.WasModified())
+
+    def test_issuing_change(self):
+        """Test Modifiable method that issues messages"""
+        self.modifiable.do_something_else()
+        # Now it should be modified and we should have received a
+        # CHANGED message
+        self.check_messages([(SOMETHING_ELSE,)])
+        self.assert_(self.modifiable.WasModified())
+
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/test/test_baserenderer.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_baserenderer.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_baserenderer.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,597 @@
+# Copyright (C) 2003, 2005, 2006 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Bernhard Reiter <bernhard at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Test Thuban.Model.baserenderer"""
+
+__version__ = "$Revision: 2712 $"
+# $Source$
+# $Id: test_baserenderer.py 2712 2006-10-15 23:27:05Z bernhard $
+
+import os
+import binascii
+import unittest
+import locale
+
+import localessupport
+from mockgeo import SimpleShapeStore
+import support
+support.initthuban()
+
+from Thuban.Model.color import Transparent, Color
+from Thuban.Model.data import SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT
+from Thuban.Model.map import Map
+from Thuban.Model.layer import BaseLayer, Layer, RasterLayer
+from Thuban.Model.table import MemoryTable, \
+     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING
+from Thuban.Model.classification import ClassGroupSingleton
+import Thuban.Model.resource
+
+
+from Thuban.UI.baserenderer import BaseRenderer, \
+     add_renderer_extension, init_renderer_extensions
+
+if Thuban.Model.resource.has_gdal_support():
+    from gdalwarp import ProjectRasterFile
+
+class MockDC:
+
+    def __init__(self, size = None):
+        self.calls = []
+        self.size = size
+
+    def GetSizeTuple(self):
+        return self.size
+
+    def __getattr__(self, attr):
+        def method(*args):
+            self.calls.append((attr,) + args)
+        return method
+
+class P:
+
+    """A simple point"""
+
+    def __init__(self, x, y):
+        self.x = x
+        self.y = y
+
+    def __eq__(self, other):
+        return self.x == other.x and self.y == other.y
+
+    def __ne__(self, other):
+        return self.x != other.x and self.y != other.y
+
+    def __repr__(self):
+        return "P(%r, %r)" % (self.x, self.y)
+
+
+class SimpleRenderer(BaseRenderer):
+
+    TRANSPARENT_PEN = ("pen", Transparent)
+    TRANSPARENT_BRUSH = ("brush", Transparent)
+
+    def make_point(self, x, y):
+        return P(x, y)
+
+    def tools_for_property(self, prop):
+        fill = prop.GetFill()
+        brush = ("brush", fill)
+
+        stroke = prop.GetLineColor()
+        stroke_width = prop.GetLineWidth()
+        if stroke is Transparent:
+            pen = ("pen", Transparent)
+        else:
+            pen = ("pen", stroke, stroke_width)
+
+        return pen, brush
+
+    def label_font(self):
+        return "label font"
+
+    def draw_raster_data(self, x, y, data, format='BMP', opacity=1.0):
+        self.raster_data = data
+        self.raster_format = format
+
+    def projected_raster_layer(self, layer, srcProj, dstProj, extents,
+                               resolution, dimensions, options):
+
+        if not Thuban.Model.resource.has_gdal_support():
+            raise support.SkipTest("No gdal support")
+
+        #print srcProj, dstProj,extents, resolution, dimensions, options
+
+        return ProjectRasterFile(layer.GetImageFilename(), 
+                                 srcProj, dstProj,
+                                 extents, resolution, dimensions, 
+                                 options)
+ 
+class MockProjection:
+
+    """Objects that look like projections but simply apply non-uniform scalings
+    """
+
+    def __init__(self, xscale, yscale):
+        self.xscale = float(xscale)
+        self.yscale = float(yscale)
+
+    def Forward(self, x, y):
+        return (x * self.xscale, y * self.yscale)
+
+    def Inverse(self, x, y):
+        return (x / self.xscale, y / self.yscale)
+
+
+class TestBaseRenderer(unittest.TestCase):
+
+    def setUp(self):
+        """Set self.to_destroy to an empty list
+
+        Tests should put all objects whose Destroy should be called at
+        the end into this list so that they're destroyed in tearDown.
+        """
+        self.to_destroy = []
+
+    def tearDown(self):
+        for obj in self.to_destroy:
+            obj.Destroy()
+
+    def test_arc_no_projection(self):
+        """Test BaseRenderer with arc layer and no projections"""
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0)])
+        shapes = [[[(0, 0), (10, 10)]]]
+        store = SimpleShapeStore(SHAPETYPE_ARC, shapes, table)
+
+        map = Map("TestBaseRenderer")
+        self.to_destroy.append(map)
+        layer = Layer("arc layer", store)
+        map.AddLayer(layer)
+
+        dc = MockDC()
+        renderer = SimpleRenderer(dc, map, 2, (10, 10))
+
+        renderer.render_map()
+
+        self.assertEquals(dc.calls,
+                          [('BeginDrawing',),
+                           ('SetBrush', ('brush', Transparent)),
+                           ('SetPen', ('pen', Color(0, 0, 0), 1)),
+                           ('DrawLines', [P(10, 10), P(30, -10)]),
+                           ('SetFont', "label font"),
+                           ('EndDrawing',)])
+
+    def test_polygon_no_projection(self):
+        """Test BaseRenderer with polygon layer and no projections"""
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0)])
+        shapes = [[[(0, 0), (10, 10), (10, 0), (0, 0)]]]
+        store = SimpleShapeStore(SHAPETYPE_POLYGON, shapes, table)
+
+        map = Map("TestBaseRenderer")
+        layer = Layer("polygon layer", store)
+        prop = layer.GetClassification().GetDefaultGroup().GetProperties()
+        prop.SetFill(Color(1, 1, 1))
+
+        map.AddLayer(layer)
+        self.to_destroy.append(map)
+
+        dc = MockDC()
+        renderer = SimpleRenderer(dc, map, 2, (10, 10))
+
+        renderer.render_map()
+
+        self.assertEquals(dc.calls,
+                          [('BeginDrawing',),
+                           ('SetBrush', ('brush', Color(1, 1, 1))),
+                           ('SetPen', ('pen', Transparent)),
+                           ('DrawPolygon', [P(10, 10), P(30, -10), P(30, 10),
+                                            P(10, 10)]),
+                           ('SetBrush', ('brush', Transparent)),
+                           ('SetPen', ('pen', Color(0, 0, 0), 1)),
+                           ('DrawLines', [P(10, 10), P(30, -10), P(30, 10),
+                                          P(10, 10)]),
+                           ('SetFont', "label font"),
+                           ('EndDrawing',)])
+
+    def test_complex_polygon(self):
+        """Test BaseRenderer with complex polygon and no projections"""
+        # A square inside a sqare. This has to be drawn with at least a
+        # draw polygon call and two draw lines calls.
+        shapes = [[[(0, 0), (0, 10), (10, 10), (10, 0), (0, 0)],
+                   [(2, 2), (8, 2), (8, 8), (2, 8), (2, 2)]]]
+
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0)])
+        store = SimpleShapeStore(SHAPETYPE_POLYGON, shapes, table)
+
+        map = Map("TestBaseRenderer")
+        layer = Layer("polygon layer", store)
+        prop = layer.GetClassification().GetDefaultGroup().GetProperties()
+        prop.SetFill(Color(1, 1, 1))
+
+        map.AddLayer(layer)
+        self.to_destroy.append(map)
+
+        dc = MockDC()
+        renderer = SimpleRenderer(dc, map, 2, (10, 10))
+
+        renderer.render_map()
+
+        self.assertEquals(dc.calls,
+                          [('BeginDrawing',),
+                           ('SetBrush', ('brush', Color(1, 1, 1))),
+                           ('SetPen', ('pen', Transparent)),
+                           ('DrawPolygon',
+                            [P(10, 10), P(10, -10), P(30, -10), P(30, 10),
+                             P(10, 10),
+                             P(14, 6), P(26, 6), P(26, -6), P(14, -6),
+                             P(14, 6),
+                             P(10, 10)]),
+                           ('SetBrush', ('brush', Transparent)),
+                           ('SetPen', ('pen', Color(0, 0, 0), 1)),
+                           ('DrawLines', [P(10, 10), P(10, -10), P(30, -10),
+                                          P(30, 10), P(10, 10)]),
+                           ('DrawLines', [P(14, 6), P(26, 6), P(26, -6),
+                                          P(14, -6), P(14, 6)]),
+                           ('SetFont', "label font"),
+                           ('EndDrawing',)])
+
+    def test_point_no_projection(self):
+        """Test BaseRenderer with point layer and no projections"""
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0),
+                             ("UNKNOWN", 0.0, 1)])
+        shapes = [[[(0, 0)]], [[(10, 10)]]]
+        store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
+
+        map = Map("TestBaseRenderer")
+        layer = Layer("point layer", store)
+        map.AddLayer(layer)
+        self.to_destroy.append(map)
+
+        dc = MockDC()
+        renderer = SimpleRenderer(dc, map, 2, (10, 10))
+
+        renderer.render_map()
+
+        self.assertEquals(dc.calls,
+                          [('BeginDrawing',),
+                           ('SetBrush', ('brush', Transparent)),
+                           ('SetPen', ('pen', Color(0, 0, 0), 1)),
+                           ('DrawEllipse', 5, 5, 10, 10),
+                           ('SetBrush', ('brush', Transparent)),
+                           ('SetPen', ('pen', Color(0, 0, 0), 1)),
+                           ('DrawEllipse', 25, -15, 10, 10),
+                           ('SetFont', "label font"),
+                           ('EndDrawing',)])
+
+    def test_projected_raster_layer(self):
+        if not Thuban.Model.resource.has_gdal_support():
+            raise support.SkipTest("No gdal support")
+
+        layer = RasterLayer("raster layer",
+                            os.path.join("..", "Data", "iceland",
+                                         "island.tif"))
+
+        dc = MockDC(size = (20, 20))
+        renderer = SimpleRenderer(dc, map, 34, (800, 2250))
+
+        # The reference data as a base64 coded RAW image
+        raw_data = binascii.a2b_base64(
+            'UmbmUmbmUmbmUmbmUmbmAtYCJooCAtICAq4CJooCArICAuICArICAuYCAs4COn4CO'
+            'n4CAq4CAuICFpICUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmAuYCAqICAqoCAqoCFp'
+            'ICJooCIo4CCpoCQnoGOn4CDpYCOn4CUmbmUmbmNo6aEpYCLoYCAqICGpICFpICUmb'
+            'mAt4CUmbmNo6aAtICArYCAqoCKoYCMoICTnYKOn4CFpICUmbmUmbmUmbmUmbmAp4C'
+            'NoICArYCAr4CCpoCAqYCCpoCEpYCHo4CFpICHo4CGpICFpICKoYCTnYKMoICAp4CU'
+            'mbmUmbmUmbmUmbmUmbmUmbmAtYCAroCArYCCpoCAtYCAroCAtICAsYCUmbmAt4CAq'
+            'YCAroCMoICAs4CAs4CAtYCAt4CAqYCUmbmUmbmUmbmUmbmAtoCAtYCAq4CAtoCBp4'
+            'CAroCAqoCAq4CAr4CDpYCGpICAt4CAsICDpYCArICCpoCHo4CAs4CAuICUmbmUmbm'
+            'UmbmUmbmUmbmUmbmAuICAqICFpYCAq4CDpoCAqYCFpICAqYCUmbmNo6aAsYCCpoCD'
+            'pYCAqICAtoCUmbmAt4CAqoCCpoCAroCHo4CAsYCAq4CAsICAs4CAp4CUmbmAtYCAq'
+            'YCIooCHo4CAsICAr4CAqICEpYCAs4CAqICArICDpYCEpYCEpYCAr4CUmbmEpYCAs4'
+            'CAtICAs4CAqYCUmbmAtoCAp4CCpoCDpYCAq4CArICAqoCAqYCAqYCAtYCAtoCDpYC'
+            'At4CUmbmUmbmUmbmUmbmAt4CAsoCAsoCAp4CAp4CCpoCAsoCAt4CNo6aUmbmUmbmU'
+            'mbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmAt4CAtYCCpoCAqICAroCAr4CUmbmUm'
+            'bmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmb'
+            'mUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm'
+            'UmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmU'
+            'mbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUm'
+            'bmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmb'
+            'mUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm'
+            'UmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmU'
+            'mbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUm'
+            'bmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmb'
+            'mUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm'
+            'UmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm\n')
+
+        raw_mask = binascii.a2b_base64(
+            '//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P//8P/'
+            '/8P//8P//8P//8P//8P\n')
+
+        raw_mask_inverted = binascii.a2b_base64(
+            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
+            'AAAAAAAAAAAAAAAAAAA\n')
+
+        raw_alpha = binascii.a2b_base64(
+            '/////////////////////////////////////////////////////////////'
+            '/////////////////////////////////////////////////////////////'
+            '/////////////////////////////////////////////////////////////'
+            '/////////////////////////////////////////////////////////////'
+            '/////////////////////////////////////////////////////////////'
+            '/////////////////////////////////////////////////////////////'
+            '/////////////////////////////////////////////////////////////'
+            '/////////////////////////////////////////////////////////////'
+            '/////////////////////////////////////////////w==\n')
+
+        for opts, data in [[1,   (raw_data, raw_mask,          None)],
+                           [1|4, (raw_data, raw_mask_inverted, None)],
+                           [2,   (raw_data, None,              raw_alpha)]]:
+
+            img_data = renderer.projected_raster_layer(layer, "", "", 
+                            (-24, 65, -23, 66), [0, 0], (20, 20), opts)
+            self.assertEquals(img_data, data)
+
+    def test_projected_raster_decimalcommalocale(self):
+        if not Thuban.Model.resource.has_gdal_support():
+            raise support.SkipTest("No gdal support")
+
+        def _do_project_island():
+            """Project island.tif and return result."""
+            layer = RasterLayer("raster layer",
+                                os.path.join("..", "Data", "iceland",
+                                             "island.tif"))
+
+            dc = MockDC(size = (10, 5))
+            renderer = SimpleRenderer(dc, map, 34, (800, 2250))
+
+            projection = "+proj=latlong +to_meter=0.017453 +ellps=clrk66"
+            new_projection = "+proj=utm +zone=27 +ellps=clrk66"
+
+            return renderer.projected_raster_layer(layer, \
+                            projection, new_projection, \
+                            (322003.1320390497, 6964094.1718668584, 876022.1891829354, 7460469.6276894147), [0, 0], (10,5), 1)
+
+        oldlocale = localessupport.setdecimalcommalocale()
+        img_data2 = _do_project_island()
+        locale.setlocale(locale.LC_NUMERIC, oldlocale)
+
+        img_data1 = _do_project_island()
+
+        self.assertEquals(img_data1, img_data2)
+
+    def test_raster_no_projection(self):
+        """Test BaseRenderer with raster layer and no projections
+
+        This test is very simple minded and perhaps can easily fail due
+        to round-off errors. It simply compares the complete BMP file
+        returned by gdalwarp.ProjectRasterFile to a BMP file data.
+        """
+        if not Thuban.Model.resource.has_gdal_support():
+            raise support.SkipTest("No gdal support")
+
+        map = Map("TestBaseRenderer")
+
+        layer = RasterLayer("raster layer",
+                            os.path.join("..", "Data", "iceland",
+                                         "island.tif"))
+        layer.SetMaskType(layer.MASK_NONE)
+
+        map.AddLayer(layer)
+        self.to_destroy.append(map)
+
+        dc = MockDC(size = (20, 20))
+        renderer = SimpleRenderer(dc, map, 34, (800, 2250))
+
+        renderer.render_map()
+
+        # The following commented out code block can be used to generate
+        # the base64 coded reference image data
+        #hexed = binascii.b2a_base64(renderer.raster_data[2][0])
+        #while hexed:
+            #print repr(hexed[:65])
+            #hexed = hexed[65:]
+
+        # The reference data as a base64 coded RAW image
+        raw_data = binascii.a2b_base64(
+            'UmbmUmbmUmbmUmbmUmbmAtYCJooCAtICAq4CJooCArICAuICArICAuYCAs4COn4CO'
+            'n4CAq4CAuICFpICUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmAuYCAqICAqoCAqoCFp'
+            'ICJooCIo4CCpoCQnoGOn4CDpYCOn4CUmbmUmbmNo6aEpYCLoYCAqICGpICFpICUmb'
+            'mAt4CUmbmNo6aAtICArYCAqoCKoYCMoICTnYKOn4CFpICUmbmUmbmUmbmUmbmAp4C'
+            'NoICArYCAr4CCpoCAqYCCpoCEpYCHo4CFpICHo4CGpICFpICKoYCTnYKMoICAp4CU'
+            'mbmUmbmUmbmUmbmUmbmUmbmAtYCAroCArYCCpoCAtYCAroCAtICAsYCUmbmAt4CAq'
+            'YCAroCMoICAs4CAs4CAtYCAt4CAqYCUmbmUmbmUmbmUmbmAtoCAtYCAq4CAtoCBp4'
+            'CAroCAqoCAq4CAr4CDpYCGpICAt4CAsICDpYCArICCpoCHo4CAs4CAuICUmbmUmbm'
+            'UmbmUmbmUmbmUmbmAuICAqICFpYCAq4CDpoCAqYCFpICAqYCUmbmNo6aAsYCCpoCD'
+            'pYCAqICAtoCUmbmAt4CAqoCCpoCAroCHo4CAsYCAq4CAsICAs4CAp4CUmbmAtYCAq'
+            'YCIooCHo4CAsICAr4CAqICEpYCAs4CAqICArICDpYCEpYCEpYCAr4CUmbmEpYCAs4'
+            'CAtICAs4CAqYCUmbmAtoCAp4CCpoCDpYCAq4CArICAqoCAqYCAqYCAtYCAtoCDpYC'
+            'At4CUmbmUmbmUmbmUmbmAt4CAsoCAsoCAp4CAp4CCpoCAsoCAt4CNo6aUmbmUmbmU'
+            'mbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmAt4CAtYCCpoCAqICAroCAr4CUmbmUm'
+            'bmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmb'
+            'mUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm'
+            'UmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmU'
+            'mbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUm'
+            'bmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmb'
+            'mUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm'
+            'UmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmU'
+            'mbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUm'
+            'bmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmb'
+            'mUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm'
+            'UmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbmUmbm\n')
+
+        self.assertEquals(renderer.raster_data, 
+                          (20,20,(raw_data, None, None)))
+
+        self.assertEquals(renderer.raster_format, "RAW")
+
+        self.assertEquals(dc.calls,
+                          [('BeginDrawing',),
+                           ('SetFont', "label font"),
+                           ('EndDrawing',)])
+
+    def test_point_map_projection(self):
+        """Test BaseRenderer with point layer and map projection"""
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0)])
+        shapes = [[[(10, 10)]]]
+        store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
+
+        map = Map("TestBaseRenderer")
+        map.SetProjection(MockProjection(-3, 3))
+        layer = Layer("point layer", store)
+        map.AddLayer(layer)
+        self.to_destroy.append(map)
+
+        dc = MockDC()
+        renderer = SimpleRenderer(dc, map, 2, (10, 10))
+
+        renderer.render_map()
+
+        self.assertEquals(dc.calls,
+                          [('BeginDrawing',),
+                           ('SetBrush', ('brush', Transparent)),
+                           ('SetPen', ('pen', Color(0, 0, 0), 1)),
+                           ('DrawEllipse', -55, -55, 10, 10),
+                           ('SetFont', "label font"),
+                           ('EndDrawing',)])
+
+    def test_point_layer_projection(self):
+        """Test BaseRenderer with point layer and layer projection"""
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0)])
+        shapes = [[[(9, 9)]]]
+        store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
+
+        map = Map("TestBaseRenderer")
+        layer = Layer("point layer", store)
+        layer.SetProjection(MockProjection(3, -3))
+        map.AddLayer(layer)
+        self.to_destroy.append(map)
+
+        dc = MockDC()
+        renderer = SimpleRenderer(dc, map, 2, (10, 10))
+
+        renderer.render_map()
+
+        self.assertEquals(dc.calls,
+                          [('BeginDrawing',),
+                           ('SetBrush', ('brush', Transparent)),
+                           ('SetPen', ('pen', Color(0, 0, 0), 1)),
+                           ('DrawEllipse', 11, 11, 10, 10),
+                           ('SetFont', "label font"),
+                           ('EndDrawing',)])
+
+    def test_point_layer_and_map_projection(self):
+        """Test BaseRenderer with point layer and layer and map projection"""
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0)])
+        shapes = [[[(9, 9)]]]
+        store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
+
+        map = Map("TestBaseRenderer")
+        map.SetProjection(MockProjection(-3, 3))
+        layer = Layer("point layer", store)
+        layer.SetProjection(MockProjection(3, -3))
+        map.AddLayer(layer)
+        self.to_destroy.append(map)
+
+        dc = MockDC()
+        renderer = SimpleRenderer(dc, map, 2, (10, 10))
+
+        renderer.render_map()
+
+        self.assertEquals(dc.calls,
+                          [('BeginDrawing',),
+                           ('SetBrush', ('brush', Transparent)),
+                           ('SetPen', ('pen', Color(0, 0, 0), 1)),
+                           ('DrawEllipse', -13, 23, 10, 10),
+                           ('SetFont', "label font"),
+                           ('EndDrawing',)])
+
+
+    def test_point_with_classification(self):
+        """Test BaseRenderer with point layer and classification"""
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0),
+                             ("UNKNOWN", 0.0, 1)])
+        shapes = [[[(0, 0)]], [[(10, 10)]]]
+        store = SimpleShapeStore(SHAPETYPE_POINT, shapes, table)
+
+        map = Map("TestBaseRenderer")
+        layer = Layer("point layer", store)
+        group = ClassGroupSingleton(1)
+        group.GetProperties().SetFill(Color(0, 0, 1))
+        layer.GetClassification().AppendGroup(group)
+        layer.SetClassificationColumn("code")
+
+        map.AddLayer(layer)
+        self.to_destroy.append(map)
+
+        dc = MockDC()
+        renderer = SimpleRenderer(dc, map, 2, (10, 10))
+
+        renderer.render_map()
+
+        self.assertEquals(dc.calls,
+                          [('BeginDrawing',),
+                           ('SetBrush', ('brush', Transparent)),
+                           ('SetPen', ('pen', Color(0, 0, 0), 1)),
+                           ('DrawEllipse', 5, 5, 10, 10),
+                           ('SetBrush', ('brush', Color(0, 0, 1))),
+                           ('SetPen', ('pen', Color(0, 0, 0), 1)),
+                           ('DrawEllipse', 25, -15, 10, 10),
+                           ('SetFont', "label font"),
+                           ('EndDrawing',)])
+
+
+    def test_renderer_extension(self):
+        """Test renderer with a renderer extension"""
+        class MyLayer(BaseLayer):
+            pass
+
+        calls = []
+        def my_renderer(renderer, layer):
+            calls.append((renderer, layer))
+            return ()
+
+        add_renderer_extension(MyLayer, my_renderer)
+
+        try:
+            map = Map("test_renderer_extension")
+            layer = MyLayer("my layer")
+            map.AddLayer(layer)
+            self.to_destroy.append(map)
+
+            dc = MockDC()
+            renderer = SimpleRenderer(dc, map, 2, (10, 10))
+            renderer.render_map()
+        finally:
+            init_renderer_extensions()
+
+        self.assertEquals(calls, [(renderer, layer)])
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_classgen.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_classgen.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_classgen.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,351 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Menu
+"""
+
+__version__ = "$Revision: 1528 $"
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.classgen import \
+    generate_singletons, \
+    generate_uniform_distribution, \
+    generate_quantiles, \
+    calculate_quantiles, \
+    grey_ramp, CustomRamp, FixedRamp
+from Thuban.Model.range import Range
+from Thuban.Model.color import Color
+
+from Thuban.Model.classification import ClassGroupRange, ClassGroupProperties
+
+class ClassGenTest(unittest.TestCase):
+
+    def doClassRangeTest(self, clazz, ranges):
+        self.assertEquals(clazz.GetNumGroups(), len(ranges))
+        for i in range(clazz.GetNumGroups()):
+            group = clazz.GetGroup(i)
+            r1 = str(Range(ranges[i]))
+            r2 = group.GetRange()
+            self.assertEquals(r1, r2)
+
+        self.doBoundsTest(clazz)
+
+    def doClassSingleTest(self, clazz, _list):
+        self.assertEquals(clazz.GetNumGroups(), len(_list))
+        for i in range(clazz.GetNumGroups()):
+            group = clazz.GetGroup(i)
+            self.assertEquals(group.GetValue(), _list[i])
+
+        self.doBoundsTest(clazz)
+
+    def doBoundsTest(self, clazz, ramp = grey_ramp):
+
+        #
+        # check that the properties are right (i.e. the first group
+        # is all white, the last is all black). This assumes that
+        # the grey_ramp, unless another is provided.
+        #
+        if clazz.GetNumGroups() >= 1:
+            groupF = clazz.GetGroup(0)
+            first = ramp.GetProperties(0)
+            self.assertEquals(groupF.GetProperties(), first)
+
+        if clazz.GetNumGroups() >= 2:
+            groupL = clazz.GetGroup(clazz.GetNumGroups() - 1)
+            last = ramp.GetProperties(1)
+            self.assertEquals(groupL.GetProperties(), last)
+            
+    def test_generate_singletons(self):
+        """Test generate_singletons"""
+
+        eq = self.assertEquals
+        gs = generate_singletons
+        ramp = grey_ramp
+
+        _list = [1, 2, 3, 4]
+        cl = gs(_list, ramp)
+        self.doClassSingleTest(cl, _list)
+
+        _list = range(0, 100)
+        cl = gs(_list, ramp)
+        self.doClassSingleTest(cl, _list)
+
+        _list = range(-100, 100)
+        cl = gs(_list, ramp)
+        self.doClassSingleTest(cl, _list)
+
+        _list = ['a', 'b', 'c', 'd']
+        cl = gs(_list, ramp)
+        self.doClassSingleTest(cl, _list)
+
+        _list = []
+        cl = gs(_list, ramp)
+        self.doClassSingleTest(cl, _list)
+
+        _list = [1]
+        cl = gs(_list, ramp)
+        self.doClassSingleTest(cl, _list)
+        
+
+    def test_generate_uniform_distribution(self):
+        """Test generate_uniform_distribution"""
+
+        eq = self.assertEquals
+        gud = generate_uniform_distribution
+        ramp = grey_ramp
+
+        cl = gud(0, 99, 10, ramp, True)
+        self.doClassRangeTest(cl, ("[0;10[", "[10;20[", "[20;30[", "[30;40[",
+                              "[40;50[", "[50;60[", "[60;70[", "[70;80[",
+                              "[80;90[", "[90;99]"))
+
+        cl = gud(0, 99, 10, ramp, False)
+        self.doClassRangeTest(cl, ("[0;9.9[", "[9.9;19.8[", "[19.8;29.7[", 
+                              "[29.7;39.6[", "[39.6;49.5[", "[49.5;59.4[", 
+                              "[59.4;69.3[", "[69.3;79.2[", "[79.2;89.1[", 
+                              "[89.1;99.0]"))
+
+        cl = gud(1, 2, 2, ramp, False)
+        self.doClassRangeTest(cl, ("[1;1.5[", "[1.5;2]"))
+
+        cl = gud(1, 2, 2, ramp, True)
+        self.doClassRangeTest(cl, ("[1;2[", "[2;2]"))
+
+
+    def test_generate_quantiles(self):
+        """Test generate_quantiles"""
+
+        eq = self.assertEquals
+
+        #
+        # Test calculate_quantiles
+        #
+
+        gq = generate_quantiles
+
+        ramp = grey_ramp
+
+        adj, cl = gq([1, 2, 3, 4], [.25, .5, .75, 1.0], ramp, Range("[1;4]"))
+        self.failIf(adj)
+        self.doClassRangeTest(cl, ("[1;1]", "]1;2]", "]2;3]", "]3;4]"))
+
+        adj, cl = gq(range(0, 100), [.25, .5, .75, 1.0], ramp, Range("[0;100["))
+        self.failIf(adj)
+        self.doClassRangeTest(cl, ("[0;24]", "]24;49]", "]49;74]", "]74;100["))
+
+        adj, cl = gq(range(0, 100), [.33, .66, 1.0], ramp, Range("[0;100]"))
+        self.failIf(adj)
+        self.doClassRangeTest(cl, ("[0;32]", "]32;65]", "]65;100]"))
+
+        # negative input
+        adj,cl = gq(range(-100,100), [.33, .66, 1.0], ramp, Range("[-100;100]"))
+        self.failIf(adj)
+        self.doClassRangeTest(cl, ("[-100;-35]", "]-35;31]", "]31;100]"))
+
+        # unequal percentiles
+        adj,cl = gq(range(0, 100), [.25, .66, .8, 1.0], ramp, Range("[0;100]"))
+        self.failIf(adj)
+        self.doClassRangeTest(cl, ("[0;24]", "]24;65]", "]65;79]", "]79;100]"))
+
+        # input all the same
+        adj,cl = gq([1, 1, 1, 1], [.25, .5, .75, 1.0], ramp, Range("[1;4]"))
+        self.failUnless(adj)
+        self.doClassRangeTest(cl, ("[1;4]",))
+
+        # empty input
+        adj,cl = gq([], [.25, .5, .75, 1.0], ramp, Range("[1;4]"))
+        self.failUnless(adj)
+        self.doClassRangeTest(cl, ())
+
+        # empty range
+        adj,cl = gq([1, 2, 3, 4], [.25, .5, .75, 1.0], ramp, Range("]0;1["))
+        self.failUnless(adj)
+        self.doClassRangeTest(cl, ())
+
+        # empty percentiles
+        self.assertRaises(ValueError, gq,
+                          [1, 2, 3, 4], [], ramp, Range("]0;1["))
+
+        # single percentile
+        self.assertRaises(ValueError, gq,
+                          [1, 2, 3, 4], [.5], ramp, Range("[0;4]"))
+
+        # more percentiles than input
+        adj,cl = gq([1], [.5, 1.0], ramp, Range("[0;4]"))
+        self.failUnless(adj)
+        self.doClassRangeTest(cl, ("[0;4]",))
+
+        adj,cl = gq([1], [.1, .2, .3, .4, .5, .6, .7, .8, .9, 1.0], ramp, Range("[0;4]"))
+        self.failUnless(adj)
+        self.doClassRangeTest(cl, ("[0;4]",))
+
+        # range smaller than the input
+        adj,cl = gq([1, 2, 3, 4], [.5, 1.0], ramp, Range("[2;3]"))
+        self.failIf(adj)
+        self.doClassRangeTest(cl, ("[2;2]","]2;3]"))
+
+        # range outside the input
+        adj,cl = gq([5, 6, 7, 8], [.5, 1.0], ramp, Range("[2;3]"))
+        self.failUnless(adj)
+        self.doClassRangeTest(cl, ())
+
+        adj,cl = gq([1, 1, 1, 1, 1, 1], [.25, .5, .75, 1.0], ramp, Range("[1;4]"))
+        self.failUnless(adj)
+        self.doClassRangeTest(cl, ("[1;4]",))
+
+        adj,cl = gq([1, 1, 1, 1, 1, 2, 3], [.25, .5, .75, 1.0], ramp, Range("[1;4]"))
+        self.failUnless(adj)
+        self.doClassRangeTest(cl, ("[1;1]", "]1;2]", "]2;4]"))
+
+        # adjusted quantiles
+        adj,cl = gq([1, 1, 1, 1, 1, 
+                     2, 2, 2, 2, 2, 
+                     3, 3, 3, 3, 3, 
+                     4, 4, 4, 4, 4,
+                     5, 5, 5, 5, 5], 
+                    [.12, .24, .36, .50, .62, .76, .88, 1.0], ramp, Range("[1;5]"))
+        
+        self.failUnless(adj)
+        self.doClassRangeTest(cl, ("[1;1]", "]1;2]", "]2;3]", "]3;4]", "]4;5]"))
+        
+    def test_calculate_quantiles(self):
+        """Test calculate_quantiles"""
+
+        eq = self.assertEquals
+
+        #
+        # Test calculate_quantiles
+        #
+
+        cq = calculate_quantiles
+
+        result = cq([1, 2, 3, 4], [.25, .5, .75, 1.0], Range("[1;4]"))
+        eq(result, (0, 0, 3, [(0, .25), (1, .5), (2, .75), (3, 1.0)]))
+
+        result = cq(range(0, 100), [.25, .5, .75, 1.0], Range("[0;100]"))
+        eq(result, (0, 0, 99, [(24, .25), (49, .5), (74, .75), (99, 1.0)]))
+
+        result = cq(range(0, 100), [.33, .66, 1.0], Range("[0;100]"))
+        eq(result, (0, 0, 99, [(32, .33), (65, .66), (99, 1.0)]))
+
+        # negative input
+        result = cq(range(-100, 100), [.33, .66, 1.0], Range("[-100;100]"))
+        eq(result, (0, 0, 199, [(65, .33), (131, .66), (199, 1.0)]))
+
+        # unequal percentiles
+        result = cq(range(0, 100), [.25, .66, .8, 1.0], Range("[0;100]"))
+        eq(result, (0, 0, 99, [(24, .25), (65, .66), (79, .8), (99, 1.0)]))
+
+        # input all the same
+        result = cq([1, 1, 1, 1], [.25, .5, .75, 1.0], Range("[1;4]"))
+        eq(result, (1, 0, 3, [(3, 1.0)]))
+
+        # empty input
+        result = cq([], [.25, .5, .75, 1.0], Range("[1;4]"))
+        eq(result, None)
+
+        # empty range
+        result = cq([1, 2, 3, 4], [.25, .5, .75, 1.0], Range("]0;1["))
+        eq(result, None)
+
+        # empty percentiles
+        self.assertRaises(ValueError, cq, [1, 2, 3, 4], [], Range("]0;1["))
+
+        # single percentile
+        self.assertRaises(ValueError, cq, [1, 2, 3, 4], [.5], Range("[0;4]"))
+
+        # percentile doesn't cover range
+        self.assertRaises(ValueError, cq, [1, 2, 3, 4], [.5,.8], Range("[0;4]"))
+
+        # more percentiles than input
+        result = cq([1], [.5, 1.0], Range("[0;4]"))
+        eq(result, (1, 0, 0, [(0, 1.0)]))
+
+        result = cq([1], [.1, .2, .3, .4, .5, .6, .7, .8, .9, 1.0], Range("[0;4]"))
+        eq(result, (1, 0, 0, [(0, 1.0)]))
+
+        # range smaller than the input
+        result = cq([1, 2, 3, 4], [.5, 1.0], Range("[2;3]"))
+        eq(result, (0, 1, 2, [(1, .5), (2, 1.0)]))
+
+        # range outside the input
+        result = cq([5, 6, 7, 8], [.5, 1.0], Range("[2;3]"))
+        eq(result, None)
+
+        result = cq([1, 1, 1, 1, 1, 1], [.25, .5, .75, 1.0], Range("[1;4]"))
+        eq(result, (1, 0, 5, [(5, 1.0)]))
+
+        result = cq([1, 1, 1, 1, 1, 2, 3], [.25, .5, .75, 1.0], Range("[1;4]"))
+        eq(result, (1, 0, 6, 
+               [(4, 0.7142857142857143), # the algorithm generated
+                (5, 0.8571428571428571), # these values, but they are
+                (6, 1.0)]))              # right.
+
+        # adjusted quantiles
+        result = cq([1, 1, 1, 1, 1, 
+                     2, 2, 2, 2, 2, 
+                     3, 3, 3, 3, 3, 
+                     4, 4, 4, 4, 4,
+                     5, 5, 5, 5, 5], 
+                    [.12, .24, .36, .50, .62, .76, .88, 1.0], Range("[1;5]"))
+        eq(result, (1, 0, 24, [(4, .2), (9, .4), (14, .6), (19, .8), (24, 1.0)]))
+
+
+class TestCustomRamp(unittest.TestCase):
+
+    def test_color_interpolation(self):
+        """Test CustomRamp color interpolation"""
+        start = ClassGroupProperties()
+        start.SetFill(Color(1, 1, 1))
+        start.SetLineColor(Color(0, 0, 0))
+
+        end = ClassGroupProperties()
+        end.SetFill(Color(1, 0, 0))
+        end.SetLineColor(Color(0, 1, 0))
+
+        ramp = CustomRamp(start, end)
+        half = ramp.GetProperties(0.5)
+        self.assertEquals(half.GetFill(), Color(1, 0.5, 0.5))
+        self.assertEquals(half.GetLineColor(), Color(0, 0.5, 0))
+
+
+class TestFixedRamp(unittest.TestCase):
+
+    def test(self):
+        """Test FixedRamp"""
+        eq = self.assertEquals
+
+        for lineColor, lineWidth, fillColor in \
+            [(None, None, None), (Color(1, 1, 1), None, None),
+             (None, 4, None), (None, None, Color(0, 1, 0)),
+             (Color(1, 1, 1), 4, None), (Color(1, 1, 1), None, Color(0, 1, 0)),
+             (None, 4, Color(0, 1, 0)), (Color(1, 1, 1), 4, Color(0, 1, 0))]:
+
+            framp = FixedRamp(grey_ramp, (lineColor, lineWidth, fillColor))
+
+            for i in [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]:
+                props = framp.GetProperties(i)
+                grey = Color(1 - i, 1 - i, 1 - i)
+                if lineColor is not None:
+                    eq(props.GetLineColor(), lineColor)
+                else:
+                    eq(props.GetLineColor(), grey)
+                if lineWidth is not None:
+                    eq(props.GetLineWidth(), lineWidth)
+                if fillColor is not None:
+                    eq(props.GetFill(), fillColor)
+                else:
+                    eq(props.GetFill(), grey)
+
+if __name__ == "__main__":
+    unittest.main()
+

Added: packages/thuban/branches/upstream/current/test/test_classification.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_classification.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_classification.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,557 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Classification class
+"""
+
+__version__ = "$Revision: 2688 $"
+# $Source$
+# $Id: test_classification.py 2688 2006-06-30 12:27:20Z frank $
+
+import unittest
+
+import support
+support.initthuban()
+
+import copy
+
+from Thuban.Model.color import Color, Transparent, Black
+from Thuban.Model.classification import \
+    Classification, ClassGroup, \
+    ClassGroupDefault, ClassGroupSingleton, ClassGroupRange,\
+    ClassGroupPattern, ClassGroupProperties
+from Thuban.Model.messages import CLASS_CHANGED
+
+from Thuban.Model.range import Range
+
+
+
+# A few colors for use by the test cases
+red = Color(1, 0, 0)
+green = Color(0, 1, 0)
+blue = Color(0, 0, 1)
+
+
+class TestClassGroupProperties(unittest.TestCase):
+
+    def test(self):
+        """Test ClassGroupProperties"""
+
+        props = ClassGroupProperties()
+        self.assertEqual(props.GetLineColor(), Black)
+        self.assertEqual(props.GetLineWidth(), 1)
+        self.assertEqual(props.GetFill(), Transparent)
+
+        props.SetLineColor(red)
+        self.assertEqual(props.GetLineColor(), red)
+
+        props.SetLineColor(blue)
+        self.assertEqual(props.GetLineColor(), blue)
+
+        props.SetLineWidth(10)
+        self.assertEqual(props.GetLineWidth(), 10)
+
+        self.assertRaises(ValueError, props.SetLineWidth, -10)
+        self.assertEqual(props.GetLineWidth(), 10)
+
+        newProps1 = ClassGroupProperties()
+        newProps2 = ClassGroupProperties()
+        self.assertNotEqual(newProps1, props)
+        self.assertEqual(newProps1, newProps2)
+
+
+class TestClassGroup(unittest.TestCase):
+
+    def test(self):
+        """Test ClassGroup"""
+
+        # test constructor with no label
+        group = ClassGroup()
+        self.assertEqual(group.GetLabel(), "")
+
+        # test constructor with label
+        group = ClassGroup("hallo")
+        self.assertEqual(group.GetLabel(), "hallo")
+
+        # test SetLabel()/GetLabel()
+        group = ClassGroup("welt")
+        group.SetLabel("hallo")
+        self.assertEqual(group.GetLabel(), "hallo")
+
+        group.SetLabel("")
+        self.assertEqual(group.GetLabel(), "")
+
+        # test Matches
+        # Matches() is a virtual function...can't test it here
+        #
+        #self.assertEqual(group.Matches(None), False)
+        #self.assertEqual(group.Matches(1), False)
+        #self.assertEqual(group.Matches("hallo"), False)
+        #self.assertEqual(group.Matches([]), False)
+
+        # test GetProperties...also a virtual function
+        #self.assertEqual(group.GetProperties(), None)
+
+
+class TestClassGroupDefault(unittest.TestCase):
+
+    def test(self):
+        """Test ClassGroupDefault"""
+
+        defProps = ClassGroupProperties()
+
+        newProps = ClassGroupProperties()
+        newProps.SetLineColor(Color(.25, .5, .75))
+        newProps.SetLineWidth(5)
+        newProps.SetFill(Color(.12, .24, .36))
+
+        # test constructor
+
+        group = ClassGroupDefault(newProps)
+        self.assertEqual(group.GetProperties(), newProps)
+
+        group = ClassGroupDefault(newProps, "hallo")
+        self.assertEqual(group.GetProperties(), newProps)
+        self.assertEqual(group.GetLabel(), "hallo")
+
+        # test empty constructor
+        group = ClassGroupDefault()
+        props = group.GetProperties()
+
+        self.assertEqual(group.GetLabel(), "")
+        self.assertEqual(defProps, props)
+
+        # test Matches()
+        self.assertEqual(group.Matches(None), True)
+        self.assertEqual(group.Matches(1), True)
+        self.assertEqual(group.Matches("hallo"), True)
+        self.assertEqual(group.Matches([]), True)
+
+        # test SetProperties()/GetProperties()
+        group.SetProperties(newProps)
+        self.assertEqual(group.GetProperties(), newProps)
+
+        # test copy
+        groupCopy = copy.copy(group)
+        self.assertEqual(group, groupCopy)
+
+
+class TestClassGroupRange(unittest.TestCase):
+
+    def test(self):
+        """Test ClassGroupRange"""
+
+        defProps = ClassGroupProperties()
+        newProps = ClassGroupProperties()
+        newProps.SetLineColor(Color(.25, .5, .75))
+        newProps.SetLineWidth(5)
+        newProps.SetFill(Color(.12, .24, .36))
+
+        # test empty constructor
+        group = ClassGroupRange()
+
+        self.assertEqual(group.GetMin(), 0)
+        self.assertEqual(group.GetMax(), 1)
+        self.assertEqual(group.GetProperties(), defProps)
+        self.assertEqual(group.GetLabel(), "")
+
+        # test SetMax()
+        self.assertRaises(ValueError, group.SetMax, 0)
+        self.assertRaises(ValueError, group.SetMax, -1)
+        self.assertEquals(group.GetMax(), 1)
+        group.SetMax(2)
+        self.assertEquals(group.GetMax(), 2)
+
+        # test SetMin()
+        self.assertRaises(ValueError, group.SetMin, 2)
+        self.assertRaises(ValueError, group.SetMin, 3)
+        self.assertEquals(group.GetMin(), 0)
+        group.SetMin(-5)
+        self.assertEquals(group.GetMin(), -5)
+
+        # test SetProperties()/GetProperties()
+        group.SetProperties(newProps)
+        self.assertEqual(group.GetProperties(), newProps)
+
+        # test SetRange()
+        self.assertRaises(ValueError, group.SetRange, (1, 0))
+        group.SetRange(Range("]-oo;6]"))
+        self.assertEqual(group.GetRange(), "]-oo;6]")
+        group.SetRange((-5, 5))
+        self.assertEqual(group.GetRange(), "[-5;5[")
+
+        # test Matches()
+        self.assertEqual(group.Matches(-6), False)
+        self.assertEqual(group.Matches(-5), True)
+        self.assertEqual(group.Matches(0), True)
+        self.assertEqual(group.Matches(4), True)
+        self.assertEqual(group.Matches(5), False)
+
+        # test copy
+        groupCopy = copy.copy(group)
+        self.assertEqual(group, groupCopy)
+
+
+class TestClassGroupSingleton(unittest.TestCase):
+
+    def test(self):
+        """Test ClassGroupSingleton"""
+
+        defProps = ClassGroupProperties()
+        newProps = ClassGroupProperties()
+        newProps.SetLineColor(Color(.25, .5, .75))
+        newProps.SetLineWidth(5)
+        newProps.SetFill(Color(.12, .24, .36))
+
+        # test empty constructor
+        group = ClassGroupSingleton()
+
+        self.assertEqual(group.GetValue(), 0)
+        self.assertEqual(group.GetProperties(), defProps)
+        self.assertEqual(group.GetLabel(), "")
+
+        # test SetProperties()/GetProperties()
+        group.SetProperties(newProps)
+        self.assertEqual(group.GetProperties(), newProps)
+
+        # test SetValue()
+        group.SetValue(5)
+        self.assertEqual(group.GetValue(), 5)
+
+        # test Matches()
+        self.assertEqual(group.Matches(0), False)
+        self.assertEqual(group.Matches(5), True)
+
+        group.SetValue("5")
+        self.assertNotEqual(group.GetValue(), 5)
+
+        # test Matches()
+        self.assertEqual(group.Matches(5), False)
+        self.assertEqual(group.Matches("5"), True)
+
+        group.SetValue("hallo")
+        self.assertEqual(group.GetValue(), "hallo")
+
+        # test Matches()
+        self.assertEqual(group.Matches("HALLO"), False)
+        self.assertEqual(group.Matches("hallo"), True)
+
+        # test copy
+        groupCopy = copy.copy(group)
+        self.assertEqual(group, groupCopy)
+
+
+class TestClassGroupPattern(unittest.TestCase):
+
+    def test(self):
+        """Test ClassGroupPattern"""
+
+        defProps = ClassGroupProperties()
+        newProps = ClassGroupProperties()
+        newProps.SetLineColor(Color(.25, .5, .75))
+        newProps.SetLineWidth(5)
+        newProps.SetFill(Color(.12, .24, .36))
+
+        # test empty constructor
+        group = ClassGroupPattern()
+
+        self.assertEqual(group.GetPattern(), "")
+        self.assertEqual(group.GetProperties(), defProps)
+        self.assertEqual(group.GetLabel(), "")
+
+        # test SetProperties()/GetProperties()
+        group.SetProperties(newProps)
+        self.assertEqual(group.GetProperties(), newProps)
+
+        # test SetPattern()
+        group.SetPattern("A")
+        self.assertEqual(group.GetPattern(), "A")
+
+        # test Matches()
+        self.assertEqual(group.Matches("CBA"), False)
+        self.assertEqual(group.Matches("ABC"), True)
+
+        group.SetPattern("a")
+        self.assertNotEqual(group.GetPattern(), "A")
+
+        # test Matches()
+        self.assertEqual(group.Matches("Abc"), False)
+        self.assertEqual(group.Matches("aBC"), True)
+
+        group.SetPattern("hallo")
+        self.assertEqual(group.GetPattern(), "hallo")
+
+        # test Matches()
+        self.assertEqual(group.Matches("HALLO"), False)
+        self.assertEqual(group.Matches("hallo"), True)
+
+        # test copy
+        groupCopy = copy.copy(group)
+        self.assertEqual(group, groupCopy)
+
+
+class TestClassification(unittest.TestCase, support.SubscriberMixin):
+
+    """Test cases for Classification"""
+
+    def setUp(self):
+        self.clazz = Classification()
+        self.clazz.Subscribe(CLASS_CHANGED, self.subscribe_with_params,
+                             CLASS_CHANGED)
+        self.clear_messages()
+
+    def tearDown(self):
+        self.clear_messages()
+        self.clazz.Destroy()
+        del self.clazz
+
+    def test_defaults(self):
+        """Test Classification default settings"""
+        self.assertEqual(self.clazz.FindGroup(-1),
+                         self.clazz.GetDefaultGroup())
+        self.assertEqual(self.clazz.GetDefaultLineColor(), Black)
+        self.assertEqual(self.clazz.GetDefaultFill(), Transparent)
+        self.assertEqual(self.clazz.GetDefaultLineWidth(), 1)
+
+        # The default group is not counted, hence 0 groups
+        self.assertEqual(self.clazz.GetNumGroups(), 0)
+
+        # No messages should have been sent so far
+        self.check_messages([])
+
+    def test_set_default_properties(self):
+        """Test Classification.SetDefaultLineColor and SetDefaultFill"""
+        # No messages so far
+        self.check_messages([])
+
+        # Change the default line color
+        self.clazz.SetDefaultLineColor(red)
+        self.assertEqual(self.clazz.GetDefaultLineColor(), red)
+        self.assertEqual(self.clazz.GetDefaultFill(), Transparent)
+        self.assertEqual(self.clazz.GetDefaultLineWidth(), 1)
+
+        self.check_messages([(CLASS_CHANGED,)])
+        self.clear_messages()
+
+        self.clazz.SetDefaultFill(green)
+        self.assertEqual(self.clazz.GetDefaultFill(), green)
+        self.assertEqual(self.clazz.GetDefaultLineColor(), red)
+        self.assertEqual(self.clazz.GetDefaultLineWidth(), 1)
+        self.check_messages([(CLASS_CHANGED,)])
+
+        self.check_messages([(CLASS_CHANGED,)])
+        self.clear_messages()
+
+        self.clazz.SetDefaultLineWidth(10)
+        self.assertEqual(self.clazz.GetDefaultFill(), green)
+        self.assertEqual(self.clazz.GetDefaultLineColor(), red)
+        self.assertEqual(self.clazz.GetDefaultLineWidth(), 10)
+        self.check_messages([(CLASS_CHANGED,)])
+
+    def test_set_default_group(self):
+        """Test Classification.SetDefaultGroup()"""
+        prop = ClassGroupProperties()
+        prop.SetLineColor(blue)
+        prop.SetLineWidth(5)
+        prop.SetFill(red)
+
+        self.clazz.SetDefaultGroup(ClassGroupDefault(prop))
+        self.assertEqual(self.clazz.GetDefaultFill(), red)
+        self.assertEqual(self.clazz.GetDefaultLineColor(), blue)
+        self.assertEqual(self.clazz.GetDefaultLineWidth(), 5)
+        self.check_messages([(CLASS_CHANGED,)])
+
+    def test_add_singleton(self):
+        """Test Classification.AppendGroup(ClassGroupSingleton())"""
+        self.assertEquals(self.clazz.FindGroup(5),
+                          self.clazz.GetDefaultGroup())
+
+        s = ClassGroupSingleton(5)
+        self.clazz.AppendGroup(s)
+        self.check_messages([(CLASS_CHANGED,)])
+        self.assertEquals(self.clazz.FindGroup(5), s)
+        self.assertEquals(self.clazz.FindGroup(0),
+                          self.clazz.GetDefaultGroup())
+
+    def test_add_range(self):
+        """Test Classification.AppendGroup(ClassGroupRange())"""
+        self.assertEquals(self.clazz.FindGroup(0),
+                          self.clazz.GetDefaultGroup())
+
+        r = ClassGroupRange((-10, 10))
+        self.clazz.AppendGroup(r)
+        self.check_messages([(CLASS_CHANGED,)])
+        self.assertEquals(self.clazz.FindGroup(-11),
+                          self.clazz.GetDefaultGroup())
+        self.assertEquals(self.clazz.FindGroup(-10), r)
+        self.assertEquals(self.clazz.FindGroup(9), r)
+        self.assertEquals(self.clazz.FindGroup(5), r)
+        self.assertEquals(self.clazz.FindGroup(10),
+                          self.clazz.GetDefaultGroup())
+
+    def test_add_pattern(self):
+        """Test Classification.AppendGroup(ClassGroupPattern())"""
+        self.assertEquals(self.clazz.FindGroup(5),
+                          self.clazz.GetDefaultGroup())
+
+        s = ClassGroupPattern("A")
+        self.clazz.AppendGroup(s)
+        self.check_messages([(CLASS_CHANGED,)])
+        self.assertEquals(self.clazz.FindGroup("A"), s)
+        self.assertEquals(self.clazz.FindGroup("B"),
+                          self.clazz.GetDefaultGroup())
+
+    def test_multiple_groups_numerical(self):
+        """Test numerical Classification with multiple groups"""
+        # two singletons matching 1 to test whether they're tested in
+        # the right order. Use a non default fill on the second to make
+        # it compare unequal to the first.
+        s1 = ClassGroupSingleton(1)
+        s1a = ClassGroupSingleton(1)
+        s1a.GetProperties().SetFill(blue)
+        # Sanity check: are they considered different?
+        self.assertNotEqual(s1, s1a)
+
+        s2 = ClassGroupSingleton(2)
+        r = ClassGroupRange((-10, 10))
+
+        self.clazz.AppendGroup(s1)
+        self.clazz.AppendGroup(s2)
+        self.clazz.AppendGroup(s1a)
+        self.clazz.AppendGroup(r)
+        self.check_messages([(CLASS_CHANGED,), (CLASS_CHANGED,),
+                             (CLASS_CHANGED,), (CLASS_CHANGED,)])
+
+        self.assertEquals(self.clazz.FindGroup(-11),
+                          self.clazz.GetDefaultGroup())
+        self.assertEquals(self.clazz.FindGroup(-10), r)
+        self.assertEquals(self.clazz.FindGroup(1), s1)
+        self.assertEquals(self.clazz.FindGroup(2), s2)
+        self.assertEquals(self.clazz.FindGroup(3), r)
+        self.assertEquals(self.clazz.FindGroup(9), r)
+        self.assertEquals(self.clazz.FindGroup(10),
+                          self.clazz.GetDefaultGroup())
+
+    def test_multiple_groups_textual(self):
+        """Test textual Classification with multiple groups"""
+        # A singleton and a pattern matching 'A' to test whether 
+        # they're tested in the right order. Use a non default fill 
+        # on the pattern to make it compare unequal to the first.
+        s = ClassGroupSingleton("A")
+        p = ClassGroupPattern("A")
+        p.GetProperties().SetFill(blue)
+        # Sanity check: are they considered different?
+        self.assertNotEqual(s, p)
+
+        self.clazz.AppendGroup(s)
+        self.clazz.AppendGroup(p)
+        self.check_messages([(CLASS_CHANGED,), (CLASS_CHANGED,)])
+
+        self.assertEquals(self.clazz.FindGroup("bca"),
+                          self.clazz.GetDefaultGroup())
+        self.assertEquals(self.clazz.FindGroup("A"), s)
+        self.assertEquals(self.clazz.FindGroup("Abc"), p)
+        self.assertEquals(self.clazz.FindGroup("abc"),
+                          self.clazz.GetDefaultGroup())
+
+    def test_insert_group(self):
+        """Test Classification.InsertGroup()"""
+        s1 = ClassGroupSingleton(1)
+        s2 = ClassGroupSingleton(2)
+        r = ClassGroupRange((0, 10))
+
+        self.clazz.AppendGroup(s1)
+        self.clazz.AppendGroup(r)
+        self.assertEquals(self.clazz.FindGroup(2), r)
+        self.clear_messages()
+
+        self.clazz.InsertGroup(1, s2)
+        self.assertEquals(self.clazz.FindGroup(2), s2)
+        self.check_messages([(CLASS_CHANGED,)])
+
+    def test_remove_group(self):
+        """Test Classification.RemoveGroup()"""
+        s1 = ClassGroupSingleton(1)
+        s2 = ClassGroupSingleton(2)
+        r = ClassGroupRange((0, 10))
+
+        self.clazz.AppendGroup(s1)
+        self.clazz.AppendGroup(s2)
+        self.clazz.AppendGroup(r)
+        self.assertEquals(self.clazz.FindGroup(2), s2)
+        self.clear_messages()
+
+        self.clazz.RemoveGroup(1)
+        self.assertEquals(self.clazz.FindGroup(2), r)
+        self.check_messages([(CLASS_CHANGED,)])
+
+    def test_replace_group(self):
+        """Test Classification.ReplaceGroup()"""
+        s1 = ClassGroupSingleton(1)
+        s2 = ClassGroupSingleton(2)
+        r = ClassGroupRange((0, 10))
+
+        self.clazz.AppendGroup(s2)
+        self.clazz.AppendGroup(r)
+        self.assertEquals(self.clazz.FindGroup(2), s2)
+        self.assertEquals(self.clazz.FindGroup(1), r)
+        self.clear_messages()
+
+        self.clazz.ReplaceGroup(0, s1)
+        self.assertEquals(self.clazz.FindGroup(2), r)
+        self.assertEquals(self.clazz.FindGroup(1), s1)
+        self.check_messages([(CLASS_CHANGED,)])
+
+    def test_deepcopy_numerical(self):
+        """Test deepcopy(numerical Classification())"""
+        self.clazz.AppendGroup(ClassGroupSingleton(5))
+        self.clazz.AppendGroup(ClassGroupRange((-10, 10)))
+
+        clazz = copy.deepcopy(self.clazz)
+
+        self.assertEquals(clazz.GetNumGroups(), self.clazz.GetNumGroups())
+
+        for i in range(clazz.GetNumGroups()):
+            self.assertEquals(clazz.GetGroup(i), self.clazz.GetGroup(i))
+
+    def test_deepcopy_textual(self):
+        """Test deepcopy(textual Classification())"""
+        self.clazz.AppendGroup(ClassGroupSingleton("A"))
+        self.clazz.AppendGroup(ClassGroupPattern("B"))
+
+        clazz = copy.deepcopy(self.clazz)
+
+        self.assertEquals(clazz.GetNumGroups(), self.clazz.GetNumGroups())
+
+        for i in range(clazz.GetNumGroups()):
+            self.assertEquals(clazz.GetGroup(i), self.clazz.GetGroup(i))
+
+
+    def test_iterator(self):
+        """Test Classification iteration"""
+        groups = [ClassGroupSingleton(5), ClassGroupSingleton(5),
+                  ClassGroupRange((-3, 3)), ClassGroupSingleton(-5),
+                  ClassGroupDefault()]
+
+        for g in groups:
+            self.clazz.AppendGroup(g)
+
+        def convert(group):
+            if isinstance(group, ClassGroupDefault):   return 0
+            if isinstance(group, ClassGroupSingleton): return 1
+            if isinstance(group, ClassGroupRange):     return 2
+
+        list = []
+        for g in self.clazz:
+            list.append(convert(g))
+
+        self.assertEquals(list, [0, 1, 1, 2, 1, 0])
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_classmapper.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_classmapper.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_classmapper.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,92 @@
+# Copyright (c) 2004 by Intevation GmbH
+# Authors:
+# Martin Schulze <joey at infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Test case for the Thuban ClassMapper.
+
+"""
+
+__version__ = "$Revision: 2298 $"
+# $Source$
+# $Id: test_classmapper.py 2298 2004-07-26 15:59:46Z joey $
+
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Lib.classmapper import ClassMapper
+
+class TestMapping(unittest.TestCase):
+
+    def test_mapper(self):
+        """
+        Test ClassMapper
+        """
+
+        class MyClass:
+            pass
+
+        class MySecondClass:
+            def hello(self):
+                return "Hello World!"
+
+        class MyThirdClass:
+            def hello(self):
+                return "Hello Earth!"
+
+        mapping = ClassMapper()
+        instance = MyClass()
+
+        # See if an empty mapping really returns False
+        #
+        self.assertEqual(mapping.get(instance), None)
+        self.assertEqual(mapping.has(instance), False)
+
+        # See if an installed mapping works
+        #
+        mapping.add(MyClass, MySecondClass)
+        self.assertEqual(mapping.get(instance), MySecondClass)
+        self.assertEqual(mapping.has(instance), True)
+
+        # Ensure that it's really the class we put in and the method
+        # is available as expected.
+        #
+        myinst = mapping.get(instance)()
+        self.assertEqual(myinst.hello(), "Hello World!")
+
+        second = ClassMapper()
+
+        # Test if a second mapper gets mixed ubp with the first one.
+        #
+        self.assertEqual(second.get(instance), None)
+
+        second.add(MyClass, MyThirdClass)
+        self.assertEqual(second.get(instance), MyThirdClass)
+        self.assertEqual(second.has(instance), True)
+
+        # Ensure that it's really the class we put in and the method
+        # is available as expected.
+        #
+        myinst = second.get(instance)()
+        self.assertEqual(myinst.hello(), "Hello Earth!")
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_color.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_color.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_color.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,86 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Thuban.Model.color module
+"""
+
+__version__ = "$Revision: 1547 $"
+# $Source$
+# $Id: test_color.py 1547 2003-08-05 12:38:58Z bh $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.color import Color, Transparent
+
+
+class TestColor(unittest.TestCase):
+
+    def test(self):
+        """Test Color"""
+        # The color objects are very simple. We just have to test
+        # whether instantiating one assigns the colors to the right
+        # instance variables and whether the correct hex string is
+        # produced
+        color = Color(0, 0.5, 1.0)
+        self.assertEquals(color.red, 0.0)
+        self.assertEquals(color.green, 0.5)
+        self.assertEquals(color.blue, 1.0)
+        self.assertEquals(color.hex().lower(), "#007fff")
+
+    def test_repr(self):
+        """Test Color repr"""
+        self.assertEquals(repr(Color(0, 0.5, 0.75)), "Color(0, 0.5, 0.75)")
+
+    def test_equality(self):
+        """Test Color equality testing"""
+        self.failUnless(Color(0, 0, 0) == Color(0.0, 0.0, 0.0))
+        self.failUnless(Color(0, 0.5, 1.0) == Color(0.0, 0.5, 1.0))
+        self.failIf(Color(0, 0.5, 1.0) == Color(0.0, 0.5, 0.75))
+        self.failIf(Color(0, 0.5, 1.0) == (0.0, 0.5, 1.0))
+        self.failIf((0, 0.5, 1.0) == Color(0.0, 0.5, 1.0))
+
+    def test_inequality(self):
+        """Test Color inequality testing"""
+        self.failIf(Color(0, 0, 0) != Color(0.0, 0.0, 0.0))
+        self.failIf(Color(0, 0.5, 1.0) != Color(0.0, 0.5, 1.0))
+        self.failUnless(Color(0, 0.5, 1.0) != Color(0.0, 0.5, 0.75))
+        self.failUnless(Color(0, 0.5, 1.0) != (0.0, 0.5, 1.0))
+        self.failUnless((0, 0.5, 1.0) != Color(0.0, 0.5, 1.0))
+
+class TestTransparent(unittest.TestCase):
+
+    def test_repr(self):
+        """Test Transparent repr"""
+        self.assertEquals(repr(Transparent), "Transparent")
+
+    def test_hex(self):
+        """Test Transparent.hex()"""
+        self.assertEquals(Transparent.hex(), "None")
+
+    def test_equality(self):
+        """Test Transparent equality testing"""
+        self.failUnless(Transparent == Transparent)
+        self.failIf(Transparent == Color(0.0, 0.5, 1.0))
+        self.failIf(Color(0.0, 0.5, 1.0) == Transparent)
+        self.failIf(None == Transparent)
+        self.failIf(Transparent == None)
+
+    def test_inequality(self):
+        """Test Transparent inequality testing"""
+        self.failIf(Transparent != Transparent)
+        self.failUnless(Transparent != Color(0.0, 0.5, 1.0))
+        self.failUnless(Color(0.0, 0.5, 1.0) != Transparent)
+        self.failUnless(None != Transparent)
+        self.failUnless(Transparent != None)
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/test/test_command.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_command.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_command.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,132 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Command class
+"""
+
+__version__ = "$Revision: 537 $"
+# $Source$
+# $Id: test_command.py 537 2003-03-14 20:43:50Z bh $
+
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.UI.command import Command, ToolCommand
+
+class MockContext:
+
+    pass
+
+
+class BaseCommandTest(unittest.TestCase):
+
+    def setUp(self):
+        self.command_args = None
+
+    def command(self, *args):
+        """Method to use as the command function.
+
+        Bind all args except self to self.command_args as a tuple.
+        """
+        self.command_args = args
+
+    def context(self):
+        """Return a context object"""
+        return MockContext()
+
+class TestCommand(BaseCommandTest):
+
+    def test_static_command(self):
+        """Test Command object with no callbacks"""
+        cmd = Command("do_something", "Do Something", self.command)
+        self.assertEquals(cmd.Name(), "do_something")
+        self.assertEquals(cmd.Title(), "Do Something")
+        self.assertEquals(cmd.HelpText(), "")
+        self.assertEquals(cmd.Icon(), "")
+        self.failIf(cmd.IsDynamic())
+        self.failIf(cmd.IsTool())
+
+        context = self.context()
+        self.assert_(cmd.Sensitive(context))
+        self.failIf(cmd.Checked(context))
+
+        # Execute the command with just the context
+        cmd.Execute(context)
+        self.assertEquals(self.command_args, (context,))
+
+        # Execute the command with additional parameters
+        cmd.Execute(context, "abc")
+        self.assertEquals(self.command_args, (context, "abc"))
+
+class TestDynamicCommand(BaseCommandTest):
+
+    def setUp(self):
+        BaseCommandTest.setUp(self)
+        self.is_sensitive = 0
+        self.is_checked = 0
+        self.dynamic_text = ""
+
+    def sensitive(self, context):
+        return self.is_sensitive
+
+    def checked(self, context):
+        return self.is_checked
+
+    def dyntext(self, context):
+        return self.dynamic_text
+
+    def context(self):
+        """Return a context object"""
+        return MockContext()
+
+    def test_dynamic_sensitivity(self):
+        """Test Command object with dynamic sensitivity"""
+        cmd = Command("do_something", "Do Something", self.command,
+                      sensitive = self.sensitive)
+        self.assert_(cmd.IsDynamic())
+
+        context = self.context()
+        self.failIf(cmd.Sensitive(context))
+        self.is_sensitive = 1
+        self.assert_(cmd.Sensitive(context))
+
+    def test_dynamic_checked(self):
+        """Test Command object with dynamic checked flag"""
+        cmd = Command("do_something", "Do Something", self.command,
+                      checked = self.checked)
+        self.assert_(cmd.IsDynamic())
+
+        context = self.context()
+        self.failIf(cmd.Checked(context))
+        self.is_checked = 1
+        self.assert_(cmd.Checked(context))
+
+    def test_dynamic_title(self):
+        """Test Command object with dynamic title"""
+        cmd = Command("do_something", "Do Something", self.command,
+                      dyntext = self.dyntext)
+        self.assert_(cmd.IsDynamic())
+        self.assert_(cmd.HasDynText())
+
+        context = self.context()
+        self.assertEquals(cmd.DynText(context), "")
+        self.dynamic_text = "A Dynamic Title"
+        self.assertEquals(cmd.DynText(context), "A Dynamic Title")
+
+    def test_tool_command(self):
+        """Test ToolCommand object"""
+        cmd = ToolCommand("do_something", "Do Something", self.command,
+                          checked = self.checked)
+        self.assert_(cmd.IsDynamic())
+        self.assert_(cmd.IsTool())
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/test/test_connector.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_connector.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_connector.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,426 @@
+# Copyright (c) 2002, 2003, 2004 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Connector class
+"""
+
+__version__ = "$Revision: 2586 $"
+# $Source$
+# $Id: test_connector.py 2586 2005-03-16 14:55:21Z bh $
+
+import sys
+import unittest
+import traceback
+
+import support
+support.initthuban()
+
+from Thuban.Lib.connector import Connector, Publisher, Conduit, ConnectorError
+
+# some messages used in the tests
+SIMPLE = "SIMPLE"
+PARAM = "PARAM"
+
+class SimplePublisher:
+
+    """A version of Publisher that uses a specific connector.
+
+    The Publisher class in Thuban.Lib.connector uses the global
+    connector in the same module.
+    """
+
+    def __init__(self, connector):
+        self.connector = connector
+
+    def __del__(self):
+        self.connector.RemovePublisher(self)
+
+    def issue(self):
+        """Issue a SIMPLE message without parameters"""
+        self.connector.Issue(self, SIMPLE)
+
+    def issue_arg(self):
+        """Issue a PARAM message with 42 as parameter"""
+        self.connector.Issue(self, PARAM, 42)
+
+
+class RealPublisher(Publisher):
+
+    """Extended version of Publisher for testing purposes.
+
+    Publisher is not intended to be used directly. It is used as a base
+    class for objects that send messages when they change. So we do just
+    that here and derive from Publisher to provide some simple methods
+    that issue messages.
+    """
+
+    def simple_action(self):
+        """Issue a SIMPLE message without parameters"""
+        self.issue(SIMPLE)
+
+    def param_action(self):
+        """Issue a PARAM message with 42 as parameter"""
+        self.issue(PARAM, 42)
+
+
+class Receiver:
+
+    """Class to be used as a generic receiver of messages.
+
+    An instance of this class has some methods that can be used as
+    subscribers for messages. These messages put information about the
+    messages they received into the public instance variable messages.
+    See the method's doc-strings for more information.
+
+    Furthermore, the class is instantiated with a test case object as
+    parameter and the instance notifies the test case when it's being
+    instantiated and deleted so that the test case can determine which
+    objects weren't deleted.
+    """
+
+    def __init__(self, testcase):
+        """Initialize the object for the given testcase.
+
+        Call the testcase's expect_delete method with self as parameter.
+        """
+        self.testcase = testcase
+        self.testcase.expect_delete(self)
+        self.reset()
+
+    def __del__(self):
+        """Tell the test case that the object has been deleted"""
+        self.testcase.deleted(self)
+
+    def reset(self):
+        """Clear the list of received messages"""
+        self.messages = []
+
+    def no_params(self):
+        """Method for subscriptions without parameters
+
+        Add the tuple ("no_params",) to self.messages
+        """
+        self.messages.append(("no_params",))
+
+    def with_params(self, *args):
+        """Method for subscriptions with parameters
+
+        Add a tuple with the string 'params' followed by the arguments
+        of this function (except for the self parameter) to
+        self.messages.
+        """
+        self.messages.append(("params",) + args)
+
+
+
+class DeletionTestMixin:
+
+    """Mixin class to check for memory leaks.
+
+    Mixin class for test that want to determine whether certain objects
+    have been destroyed.
+
+    This class maintains two lists, deleted_objects and
+    expected_deletions to determine whether all objects which are
+    expected to be deleted by a test are actually deleted.
+    """
+
+    def setUp(self):
+        """Initialize self.deleted_objects and self.expected_deletions"""
+        self.deleted_objects = []
+        self.expected_deletions = []
+
+    def expect_delete(self, obj):
+        """Append the id of obj to the self.expected_deletions"""
+        self.expected_deletions.append(id(obj))
+
+    def deleted(self, obj):
+        """Append the id of obj to the self.deleted_objects"""
+        self.deleted_objects.append(id(obj))
+
+    def check_deletions(self):
+        """Assert equality of self.expected_deletions and self.deleted_objects
+
+        This check simply compares the lists for equality and thus
+        effectively assumes that the objects are deleted in the same
+        order in which they're added to the list which if used only for
+        Receiver instances is the order in which they're instantiated.
+        """
+        self.assertEquals(self.expected_deletions, self.deleted_objects)
+
+
+class ConnectorTest(unittest.TestCase, DeletionTestMixin):
+
+    """Test cases for the Connector class.
+
+    These tests use the SimplePublisher class instead of the Publisher
+    class in Thuban.Lib.connector because we only want to test the
+    connector here.
+    """
+
+    def setUp(self):
+        """Extend the inherited method to create a Connector instance.
+
+        Bind the Connector to self.connector.
+        """
+        self.connector = Connector()
+        DeletionTestMixin.setUp(self)
+
+    def test_issue_simple(self):
+        """Test connector issue without parameters"""
+        # Make a publisher and a subscriber and connect the two
+        pub = SimplePublisher(self.connector)
+        rec = Receiver(self)
+        self.connector.Connect(pub, SIMPLE, rec.no_params, ())
+
+        # now the publisher should have subscribers
+        self.assert_(self.connector.HasSubscribers(pub))
+
+        # Issue a message and check whether the receiver got it
+        pub.issue()
+        self.assertEquals(rec.messages, [("no_params",)])
+        rec.reset()
+
+        # disconnect and check that the message doesn't get send anymore
+        self.connector.Disconnect(pub, SIMPLE, rec.no_params, ())
+        pub.issue()
+        self.assertEquals(rec.messages, [])
+
+        # now the publisher should have no subscribers
+        self.failIf(self.connector.HasSubscribers(pub))
+
+        # make sure that all references have been deleted
+        del rec
+        self.check_deletions()
+
+    def test_issue_param(self):
+        """Test connector issue with parameters"""
+        pub = SimplePublisher(self.connector)
+        rec = Receiver(self)
+        # Three cases: 1. The parameter supplied by pub.issue_arg, 2.
+        # only the parameter given when connecting, 3. both
+        self.connector.Connect(pub, PARAM, rec.with_params, ())
+        self.connector.Connect(pub, SIMPLE, rec.with_params, ("deliverator",))
+        self.connector.Connect(pub, PARAM, rec.with_params, ("loglo",))
+
+        pub.issue_arg()
+        pub.issue()
+        self.assertEquals(rec.messages, [("params", 42),
+                                         ("params", 42, "loglo"),
+                                         ("params", "deliverator")])
+
+        # make sure that all references have been deleted
+        self.connector.RemovePublisher(pub)
+        del rec
+        self.check_deletions()
+
+    def test_cyclic_references(self):
+        """Test whether connector avoids cyclic references"""
+        pub = SimplePublisher(self.connector)
+        rec = Receiver(self)
+        self.connector.Connect(pub, SIMPLE, rec.no_params, ())
+
+        # deleting pub and rec should be enough that the last reference
+        # to rec has been dropped because the connector doesn't keep
+        # references to the publishers and SimplePublisher's __del__
+        # method removes all subscriptions
+        del pub
+        del rec
+        self.check_deletions()
+
+    def test_disconnect_in_receiver(self):
+        """Test unsubscribing from a channel while receiving a message
+
+        There was a bug in the connector implementation in the following
+        situation:
+
+         - 2 receivers for the same channel
+
+         - the reiver called first unsubscribes itself from that channel
+           in response to a message on that channel
+
+        Now the second receiver is never called because the list of
+        receivers was modified by Disconnect while the connecter was
+        iterating over it.
+        """
+        messages = []
+        def rec1(*args):
+            try:
+                messages.append("rec1")
+                self.connector.Disconnect(None, SIMPLE, rec1, ())
+            except:
+                self.fail("Exception in rec1")
+        def rec2(*args):
+            try:
+                messages.append("rec2")
+                self.connector.Disconnect(None, SIMPLE, rec2, ())
+            except:
+                self.fail("Exception in rec1")
+
+        self.connector.Connect(None, SIMPLE, rec1, ())
+        self.connector.Connect(None, SIMPLE, rec2, ())
+
+        self.connector.Issue(None, SIMPLE)
+
+        self.assertEquals(messages, [("rec1"), ("rec2")])
+
+
+class TestPublisher(unittest.TestCase, DeletionTestMixin):
+
+    """Tests for the Publisher class"""
+
+    def setUp(self):
+        DeletionTestMixin.setUp(self)
+
+    def test_issue_simple(self):
+        """Test Publisher message without parameters"""
+        # Make a publisher and a subscriber and connect the two
+        pub = RealPublisher()
+        rec = Receiver(self)
+        pub.Subscribe(SIMPLE, rec.no_params)
+
+        # Issue a message and check whether the receiver got it
+        pub.simple_action()
+        self.assertEquals(rec.messages, [("no_params",)])
+        rec.reset()
+
+        # disconnect and check that the message doesn't get sent anymore
+        pub.Unsubscribe(SIMPLE, rec.no_params)
+        pub.simple_action()
+        self.assertEquals(rec.messages, [])
+
+        # make sure that all references have been deleted
+        del rec
+        self.check_deletions()
+
+    def test_issue_param(self):
+        """Test Publisher message with parameters"""
+        pub = RealPublisher()
+        rec = Receiver(self)
+        # Three cases: 1. The parameter supplied by pub.issue_arg, 2.
+        # only the parameter given when connecting, 3. both
+        pub.Subscribe(PARAM, rec.with_params)
+        pub.Subscribe(SIMPLE, rec.with_params, "deliverator")
+        pub.Subscribe(PARAM, rec.with_params, "loglo")
+
+        pub.param_action()
+        pub.simple_action()
+        self.assertEquals(rec.messages, [("params", 42),
+                                         ("params", 42, "loglo"),
+                                         ("params", "deliverator")])
+
+        # make sure that all references have been deleted
+        pub.Destroy()
+        del rec
+        self.check_deletions()
+
+    def test_cyclic_references(self):
+        """Test whether Publisher avoids cyclic references"""
+        pub = RealPublisher()
+        rec = Receiver(self)
+        pub.Subscribe(SIMPLE, rec.no_params, ())
+
+        # deleting pub and rec should be enough that the last reference
+        # to rec has been dropped because the connector doesn't keep
+        # references to the publishers and SimplePublisher's __del__
+        # method removes all subscriptions
+        del pub
+        del rec
+        self.check_deletions()
+
+    def test_unsubscribe_after_destroy(self):
+        """Test that Unsubscribe() does not raise exceptions after a Destroy"""
+        pub = RealPublisher()
+        rec = Receiver(self)
+        pub.Subscribe(SIMPLE, rec.no_params)
+
+        # Sanity check: Issue a message and check whether the receiver
+        # got it
+        pub.simple_action()
+        self.assertEquals(rec.messages, [("no_params",)])
+        rec.reset()
+
+        # Now the real test. Destroy the publisher and Unsubscribe the
+        # receiver afterwards. The Unsubscribe should not raise an
+        # exception.
+        pub.Destroy()
+        try:
+            pub.Unsubscribe(SIMPLE, rec.no_params)
+        except ConnectorError:
+            self.fail("Unsubscribe after Destroy raised exception:\n"+
+                      "".join(traceback.format_exception(*sys.exc_info())))
+
+
+class MyConduit(Conduit):
+
+    """Class for use in the Conduit tests
+
+    Like publishers Conduits are not instantiated themselves they're
+    always used as base classes.
+    """
+
+    def __init__(self, forward):
+        self.forward = forward
+        self.subscribe_forwarding(SIMPLE, self.forward)
+
+    def set_forward(self, forward):
+        # NOTE: The fact the we simply pass self.forward through to
+        # unsubscribe_forwarding and subscribe_forwarding is used by the
+        # test for None handling.
+        self.unsubscribe_forwarding(SIMPLE, self.forward)
+        self.forward = forward
+        self.subscribe_forwarding(SIMPLE, self.forward)
+
+    def action(self):
+        self.delegate.param_action()
+
+
+class TestConduit(unittest.TestCase, support.SubscriberMixin):
+
+    """Tests for the Conduit class"""
+
+    def setUp(self):
+        self.publisher = RealPublisher()
+        self.other_publisher = RealPublisher()
+        self.clear_messages()
+
+    def tearDown(self):
+        self.clear_messages()
+        self.publisher.Destroy()
+        self.other_publisher.Destroy()
+        self.publisher = self.other_publisher = None
+
+    def test_forwarding(self):
+        """Test conduit forwarding"""
+        cond = MyConduit(self.publisher)
+        cond.Subscribe(SIMPLE, self.subscribe_with_params, SIMPLE)
+        self.publisher.simple_action()
+        self.check_messages([(SIMPLE,)])
+        self.clear_messages()
+
+        # Set a different publisher. The message of the new publisher
+        # will be forwarded through the conduit but not that of the old
+        # one anymore
+        cond.set_forward(self.other_publisher)
+        self.other_publisher.simple_action()
+        self.check_messages([(SIMPLE,)])
+        self.clear_messages()
+
+        self.publisher.simple_action()
+        self.check_messages([])
+        self.clear_messages()
+
+    def test_none_handling(self):
+        """Test whether (un)subscribe_forwarding work with None"""
+        # All we test is whether it works without raising exceptions :)
+        cond = MyConduit(None)
+        cond.set_forward(None)
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_csv_table.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_csv_table.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_csv_table.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,78 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""
+Test the CSV table export
+"""
+
+__version__ = "$Revision"
+# $Source$
+# $Id: test_csv_table.py 1398 2003-07-10 14:55:49Z jonathan $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.table import MemoryTable, \
+     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING, \
+     table_to_csv
+
+class TestCSVTable(unittest.TestCase, support.FileTestMixin):
+
+    def setUp(self):
+        """Create a simple table and write to file."""
+        self.table = MemoryTable([("type", FIELDTYPE_STRING),
+                                  ("value", FIELDTYPE_DOUBLE),
+                                  ("code", FIELDTYPE_INT)],
+                                 [("UNKNOWN", 0.0, 0),
+                                  ("Foo", 0.5, -1),
+                                  ("Foo", 0.25, 100),
+                                  ("bar", 1e10, 17)])
+
+    def test_table_to_cvs(self):
+        """Test table_to_csv()"""
+        filename = self.temp_file_name("test_export_csv.csv")
+        table_to_csv(self.table, filename)
+        file = open(filename, "r")
+
+        # Tile line
+        line=file.readline()
+        self.assertEquals(line,'#type,value,code\n')
+
+        # Data lines
+        line=file.readline()
+        self.assertEquals(line,'UNKNOWN,0.0,0\n')
+
+        line=file.readline()
+        self.assertEquals(line,'Foo,0.5,-1\n')
+
+        line=file.readline()
+        self.assertEquals(line,'Foo,0.25,100\n')
+
+        line=file.readline()
+        self.assertEquals(line,'bar,10000000000.0,17\n')
+        self.assertEquals(file.readline(),'')
+
+        # save selected records
+        table_to_csv(self.table, filename, [1, 3])
+        file = open(filename, "r")
+
+        # Tile line
+        line=file.readline()
+        self.assertEquals(line,'#type,value,code\n')
+
+        # Data lines
+        line=file.readline()
+        self.assertEquals(line,'Foo,0.5,-1\n')
+
+        line=file.readline()
+        self.assertEquals(line,'bar,10000000000.0,17\n')
+        self.assertEquals(file.readline(),'')
+        
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_dbf_table.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_dbf_table.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_dbf_table.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,257 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the DBFTable class
+"""
+
+__version__ = "$Revision: 1662 $"
+# $Source$
+# $Id: test_dbf_table.py 1662 2003-08-27 13:51:01Z bh $
+
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.table import DBFTable, MemoryTable, \
+     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING, \
+     table_to_dbf
+import dbflib
+
+class TestTableToDBF(unittest.TestCase, support.FileTestMixin):
+
+    def test_table_to_dbf(self):
+        """Test table_to_dbf"""
+        memtable = MemoryTable([("type", FIELDTYPE_STRING),
+                                ("value", FIELDTYPE_DOUBLE),
+                                ("code", FIELDTYPE_INT)],
+                               [("UNKNOWN", 0.0, 0),
+                                ("Foo", 0.5, -1),
+                                ("Foo", 1.0/256, 100),
+                                ("bar", 1e10, 17)])
+
+        filename = self.temp_file_name("test_table_to_dbf.dbf")
+        table_to_dbf(memtable, filename)
+
+        dbf = dbflib.DBFFile(filename)
+        self.assertEquals(dbf.read_record(2),
+                          {'code': 100, 'type': 'Foo', 'value': 0.00390625})
+        self.assertEquals(dbf.field_count(), 3)
+        self.assertEquals(dbf.record_count(), 4)
+        self.assertEquals(dbf.field_info(0),
+                          (dbflib.FTString, "type", 7, 0))
+        self.assertEquals(dbf.field_info(1),
+                          (dbflib.FTDouble, "value", 24, 12))
+        self.assertEquals(dbf.field_info(2),
+                          (dbflib.FTInteger, "code", 3, 0))
+
+        # save selected rows
+        table_to_dbf(memtable, filename, [1, 3])
+
+        dbf = dbflib.DBFFile(filename)
+        self.assertEquals(dbf.read_record(0),
+                          {'code': -1, 'type': 'Foo', 'value': 0.5})
+        self.assertEquals(dbf.field_count(), 3)
+        self.assertEquals(dbf.record_count(), 2)
+        self.assertEquals(dbf.field_info(0),
+                          (dbflib.FTString, "type", 7, 0))
+        self.assertEquals(dbf.field_info(1),
+                          (dbflib.FTDouble, "value", 24, 12))
+        self.assertEquals(dbf.field_info(2),
+                          (dbflib.FTInteger, "code", 3, 0))
+
+    def test_table_to_dbf_long_col_names(self):
+        """Test table_to_dbf with long column names."""
+        memtable = MemoryTable([("SOME_STRING", FIELDTYPE_STRING),
+                                ("SOME_LONG_COLNAME", FIELDTYPE_DOUBLE),
+                                ("SOME_LONG_COLNAME_2", FIELDTYPE_DOUBLE)],
+                               [("UNKNOWN", 0.0, 0.0),
+                                ("Foo", 1.0, 0.0),
+                                ("Foo", 478.23482182999999, 0.0),
+                                ("bar", -2.25, 1.0)])
+
+        filename = self.temp_file_name("test_table_to_dbf_long_col_names.dbf")
+        table_to_dbf(memtable, filename)
+
+        dbf = dbflib.DBFFile(filename)
+        self.assertEquals(dbf.read_record(3),
+                          {'SOME_STRIN': "bar", 'SOME_LONG_': -2.25,
+                           'SOME_LONG1': 1.0})
+
+class TestDBFTable(unittest.TestCase, support.FileTestMixin):
+
+    def setUp(self):
+        """Create a new dbf file. The name is in self.filename"""
+        simple = MemoryTable([("type", FIELDTYPE_STRING),
+                              ("value", FIELDTYPE_DOUBLE),
+                              ("code", FIELDTYPE_INT)],
+                             [("UNKNOWN", 0.0, 0),
+                              ("Foo", 0.5, -1),
+                              ("Foo", 0.25, 100),
+                              ("bar", 1e10, 17)])
+
+        self.filename = self.temp_file_name("test_dbf_read.dbf")
+        table_to_dbf(simple, self.filename)
+
+    def test_num_rows(self):
+        """Test DBFTable.NumRows()"""
+        table = DBFTable(self.filename)
+        self.assertEquals(table.NumRows(), 4)
+
+    def test_num_columns(self):
+        """Test DBFTable.NumColumns()"""
+        table = DBFTable(self.filename)
+        self.assertEquals(table.NumColumns(), 3)
+
+    def test_columns(self):
+        """Test DBFTable.Columns()"""
+        table = DBFTable(self.filename)
+        columns = table.Columns()
+        self.assertEquals(columns[0].name, "type")
+        self.assertEquals(columns[0].type, FIELDTYPE_STRING)
+        self.assertEquals(columns[1].name, "value")
+        self.assertEquals(columns[1].type, FIELDTYPE_DOUBLE)
+        self.assertEquals(columns[2].name, "code")
+        self.assertEquals(columns[2].type, FIELDTYPE_INT)
+
+    def test_column(self):
+        """Test DBFTable.Column()"""
+        table = DBFTable(self.filename)
+        # The Column method can be called with either an index or a name
+        col = table.Column(2)
+        self.assertEquals(col.name, "code")
+        self.assertEquals(col.type, FIELDTYPE_INT)
+        col = table.Column("value")
+        self.assertEquals(col.name, "value")
+        self.assertEquals(col.type, FIELDTYPE_DOUBLE)
+
+    def test_has_column(self):
+        """Test DBFTable.HasColumn()"""
+        table = DBFTable(self.filename)
+        # HasColumn
+        self.failUnless(table.HasColumn("value"))
+        self.failUnless(table.HasColumn(2))
+        # HasColumn for non-exisiting columns
+        self.failIf(table.HasColumn("non_existing_name"))
+        self.failIf(table.HasColumn(100))
+
+    def test_read_row_as_dict(self):
+        """Test DBFTable.ReadRowAsDict()"""
+        table = DBFTable(self.filename)
+        self.assertEquals(table.ReadRowAsDict(1),
+                          {"type": "Foo", "value": 0.5, "code": -1})
+
+    def test_read_row_as_dict_row_count_mode(self):
+        """Test DBFTable.ReadRowAsDict() row count address mode"""
+        table = DBFTable(self.filename)
+        self.assertEquals(table.ReadRowAsDict(1, row_is_ordinal = 1),
+                          {"type": "Foo", "value": 0.5, "code": -1})
+
+    def test_read_value(self):
+        """Test DBFTable.ReadValue()"""
+        table = DBFTable(self.filename)
+        # The column in ReadValue may be given as either name or index
+        self.assertEquals(table.ReadValue(2, 0), "Foo")
+        self.assertEquals(table.ReadValue(3, "code"), 17)
+
+    def test_read_value_row_count_mode(self):
+        """Test DBFTable.ReadValue() row count address mode"""
+        table = DBFTable(self.filename)
+        # The column in ReadValue may be given as either name or index
+        self.assertEquals(table.ReadValue(2, 0, row_is_ordinal = 1), "Foo")
+        self.assertEquals(table.ReadValue(3, "code", row_is_ordinal = 1), 17)
+
+    def test_row_id_to_ordinal(self):
+        """Test DBFTable.RowIdToOrdinal()"""
+        table = DBFTable(self.filename)
+        self.assertEquals(table.RowIdToOrdinal(5), 5)
+
+    def test_row_oridnal_to_id(self):
+        """Test DBFTable.RowOrdinalToId()"""
+        table = DBFTable(self.filename)
+        self.assertEquals(table.RowOrdinalToId(5), 5)
+
+    def test_value_range(self):
+        """Test DBFTable.ValueRange()"""
+        table = DBFTable(self.filename)
+        self.assertEquals(table.ValueRange("code"), (-1, 100))
+        self.assertEquals(table.ValueRange(1), (0, 1e10))
+
+    def test_unique_values(self):
+        """Test DBFTable.UniqueValues()"""
+        table = DBFTable(self.filename)
+
+        # The column can be specified by name or index
+        self.assertEquals(table.UniqueValues("type"),
+                          ["Foo", "UNKNOWN", "bar"])
+        self.assertEquals(table.UniqueValues(2), [-1, 0, 17, 100])
+
+    def test_dependencies(self):
+        """Test DBFTable.Dependencies()"""
+        # A DBFTable doesn't have dependencies
+        table = DBFTable(self.filename)
+        self.assertEquals(len(table.Dependencies()), 0)
+
+    def test_filename(self):
+        """Test DBFTable.FileName()"""
+        # A DBFTable doesn't have dependencies
+        table = DBFTable(self.filename)
+        self.assertEquals(table.FileName(), self.filename)
+
+    def test_title(self):
+        """Test DBFTable.Title()"""
+        # A DBFTable doesn't have dependencies
+        table = DBFTable(self.filename)
+        self.assertEquals(table.Title(), "test_dbf_read")
+
+
+class TestDBFTableWriting(unittest.TestCase, support.FileTestMixin):
+
+    def test_write(self):
+        """Test DBFTable.write_record()"""
+        eq = self.assertEquals
+
+        # First create a DBF file
+        dbffilename = self.temp_file_name("dbftable_write.dbf")
+        dbf = dbflib.create(dbffilename)
+        dbf.add_field("NAME", dbflib.FTString, 20, 0)
+        dbf.add_field("INT", dbflib.FTInteger, 10, 0)
+        dbf.add_field("FLOAT", dbflib.FTDouble, 10, 4)
+        dbf.write_record(0, {'NAME': "Weatherwax", "INT":1,
+                             "FLOAT":3.1415926535})
+        dbf.close()
+
+        # Create the table
+        table = DBFTable(dbffilename)
+        record = table.ReadRowAsDict(0)
+        # The FLOAT value is different from above because of rounding
+        eq(record, {'NAME': "Weatherwax", "INT":1, "FLOAT":3.1415999999999999})
+
+        # change only one field
+        table.write_record(0, {"NAME": "Ogg"})
+        # check whether it has been written immediately
+        dbf = dbflib.DBFFile(dbffilename)
+        control = dbf.read_record(0)
+        eq(control, {'NAME': "Ogg", "INT":1, "FLOAT":3.1415999999999999})
+        dbf.close()
+
+        # check whether the table itself returns the new value
+        eq(table.ReadRowAsDict(0),
+           {'NAME': "Ogg", "INT":1, "FLOAT":3.1415999999999999})
+
+        # Check whether we can specify the record as a tuple
+        table.write_record(0, ("Garlick", 2, 1.5))
+        eq(table.ReadRowAsDict(0), {"NAME": "Garlick", "INT": 2, "FLOAT": 1.5})
+
+        table.Destroy()
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_derivedshapestore.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_derivedshapestore.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_derivedshapestore.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,130 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Tests for DerivedShapeStore"""
+
+__version__ = "$Revision: 1784 $"
+# $Source$
+# $Id: test_derivedshapestore.py 1784 2003-10-07 17:17:22Z bh $
+
+import os
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.data import DerivedShapeStore, ShapefileStore, \
+     SHAPETYPE_ARC, RAW_SHAPEFILE
+
+from Thuban.Model.session import Session
+from Thuban.Model.table import MemoryTable, \
+     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING
+
+
+class TestDerivedShapeStore(unittest.TestCase, support.FloatComparisonMixin):
+
+    def setUp(self):
+        """Initialize self.session"""
+        self.session = Session("Test Session")
+        self.filename = os.path.join("..", "Data", "iceland",
+                                "roads-line.shp")
+        self.store = ShapefileStore(self.session, self.filename)
+
+        self.table = MemoryTable([("type", FIELDTYPE_STRING),
+                                  ("value", FIELDTYPE_DOUBLE),
+                                  ("code", FIELDTYPE_INT)],
+                                 [("UNKNOWN", 0.0, 0)] * 839)
+        self.derived = DerivedShapeStore(self.store, self.table)
+
+    def tearDown(self):
+        """Call self.session.Destroy() and reset self.session to None"""
+        self.session.Destroy()
+        self.session = None
+
+    def test_dependencies(self):
+        """Test DerivedShapeStore dependencies"""
+        # The shapestore itself depends on nothing else
+        self.assertEquals(self.derived.Dependencies(),
+                          (self.store, self.table))
+
+    def test_orig_shapestore(self):
+        """Test DerivedShapeStore.OrigShapeStore()"""
+        self.assertEquals(self.derived.OrigShapeStore(), self.store)
+
+    def test_shape_type(self):
+        """Test DerivedShapeStore.ShapeType() with arc shapes"""
+        self.assertEquals(self.derived.ShapeType(), SHAPETYPE_ARC)
+
+    def test_raw_format(self):
+        """Test DerivedShapeStore.RawShapeFormat() with shapefiles"""
+        self.assertEquals(self.derived.RawShapeFormat(), RAW_SHAPEFILE)
+
+    def test_boundingbox(self):
+        """Test DerivedShapeStore.BoundingBox() with arc shapes"""
+        self.assertFloatSeqEqual(self.derived.BoundingBox(),
+                                 [-24.450359344482422, 63.426830291748047,
+                                  -13.55668830871582, 66.520111083984375])
+
+    def test_num_shapes(self):
+        """Test DerivedShapeStore.NumShapes() with arc shapes"""
+        self.assertEquals(self.derived.NumShapes(), 839)
+
+    def test_shapes_in_region(self):
+        """Test DerivedShapeStore.ShapesInRegion() with arc shapes"""
+        shapes = self.derived.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
+        self.assertEquals([s.ShapeID() for s in shapes],
+                          [613, 726, 838])
+
+    def test_all_shapes(self):
+        """Test DerivedShapeStore.AllShapes()"""
+        self.assertEquals([s.ShapeID() for s in self.store.AllShapes()],
+                          range(self.store.NumShapes()))
+
+    def test_shape(self):
+        """Test DerivedShapeStore.Shape() with arc shapes"""
+        self.assertPointListEquals(self.derived.Shape(32).Points(),
+                                   [[(-15.08217430114746, 66.2773818969726),
+                                     (-15.02635002136230, 66.2733917236328)]])
+    def test_shape_shapeid(self):
+        """Test DerivedShapeStore.Shape(i).ShapeID()"""
+        self.assertEquals(self.store.Shape(5).ShapeID(), 5)
+
+
+
+class TestDerivedShapeStoreExceptions(unittest.TestCase):
+
+    """Test DerivedShapeStore exceptions"""
+
+    def tearDown(self):
+        if hasattr(self, "session"):
+            self.session.Destroy()
+            self.session = None
+
+    def test_table_with_wrong_size(self):
+        """Test DerivedShapeStore() with a table with the wrong number of lines
+        """
+        filename = os.path.join("..", "Data", "iceland", "roads-line.shp")
+        session = self.session = Session("TestDerivedShapeStore Session")
+        store =  session.OpenShapefile(filename)
+
+        table = MemoryTable([("type", FIELDTYPE_STRING),
+                             ("value", FIELDTYPE_DOUBLE),
+                             ("code", FIELDTYPE_INT)],
+                            [("UNKNOWN", 0.0, 0),
+                             ("Foo", 0.5, -1),
+                             ("Foo", 0.25, 100),
+                             ("bar", 1e10, 17)])
+
+        # Trying to create a DerivedShapeStore where the number of lines
+        # in the table is not the same as the number of shapes in the
+        # shapefile raises a ValueError
+        self.assertRaises(ValueError, DerivedShapeStore, store, table)
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_export.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_export.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_export.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,57 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Thuban export calculations
+"""
+
+__version__ = "$Revision: 1454 $"
+# $Source$
+# $Id: test_export.py 1454 2003-07-18 14:41:04Z bh $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.UI.viewport import output_transform
+
+class TestScalebar(unittest.TestCase, support.FloatComparisonMixin):
+
+    """Test cases for the Thuban export calculations
+    """
+
+    def test_output_transform(self):
+        """Test output_transform()."""
+
+        scale, offset, mapregion = output_transform(1.0, (0,0),
+                                                   (200, 100), (200, 100))
+        self.assertFloatEqual(0.3, scale)
+        self.assertFloatSeqEqual((0.0, 0.0), offset)
+        self.assertFloatSeqEqual((20.0, 20.0, 80.0, 80.0), mapregion)
+
+        scale, offset, mapregion = output_transform(1.0, (0,0),
+                                                   (200, 100), (100, 200))
+        self.assertFloatEqual(0.16, scale)
+        self.assertFloatSeqEqual((0.0, 0.0), offset)
+        self.assertFloatSeqEqual((20.0, 20.0, 52.0, 52.0), mapregion)
+
+        scale, offset, mapregion = output_transform(1.0, (5,5),
+                                                   (200, 100), (100, 100))
+        self.assertFloatEqual(0.16, scale)
+        self.assertFloatSeqEqual((0.8, 0.8), offset)
+        self.assertFloatSeqEqual((20.0, 20.0, 52.0, 52.0), mapregion)
+
+        scale, offset, mapregion = output_transform(1.0, (0,0),
+                                                   (200, 100), (200, 200))
+        self.assertFloatEqual(0.52, scale)
+        self.assertFloatSeqEqual((0.0, 0.0), offset)
+        self.assertFloatSeqEqual((20, 20, 124.0, 124.0), mapregion)
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/test/test_fileutil.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_fileutil.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_fileutil.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,67 @@
+# Copyright (c) 2002 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the functions in Thuban.Lib.fileutil
+"""
+
+__version__ = "$Revision: 340 $"
+# $Source$
+# $Id: test_fileutil.py 340 2002-09-20 17:32:59Z bh $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Lib.fileutil import relative_filename_posix, relative_filename_nt
+
+class TestRelativeFilename(unittest.TestCase):
+
+    """Test cases for the relative_filename function."""
+
+    def test_posix(self):
+        """Test relative_filename posix version"""
+        self.assertEquals(relative_filename_posix("/usr/local/lib/",
+                                                  "/usr/local/lib/python"),
+                          'python')
+        self.assertEquals(relative_filename_posix("/usr/local/lib/",
+                                                  "/usr/local/bin/python"),
+                          '../bin/python')
+        self.assertEquals(relative_filename_posix("/usr/local/lib/",
+                                                  "/usr/bin/python"),
+                          '../../bin/python')
+        self.assertEquals(relative_filename_posix("/usr/local/lib/",
+                                                  "/var/spool/mail"),
+                          '/var/spool/mail')
+        self.assertEquals(relative_filename_posix("/home/", "xyzzy"),
+                          'xyzzy')
+        self.assertRaises(TypeError,
+                          relative_filename_posix, "home/", "/xyzzy")
+
+    def test_nt(self):
+        """Test relative_filename nt version"""
+        self.assertEquals(relative_filename_nt(r"C:\Programme\Python",
+                                               r"C:\Programme\Thuban"),
+                          '..\\Thuban')
+        self.assertEquals(relative_filename_nt(r"C:\Programme\Python",
+                                               r"D:\Programme\Thuban"),
+                          'D:\\Programme\\Thuban')
+        self.assertEquals(relative_filename_nt(r"C:\Programme\Python",
+                                               r"C:Programme"),
+                          'C:Programme')
+        # first argument is not an absolute filename
+        self.assertRaises(TypeError, relative_filename_nt,
+                          r"C:Programme\Python", r"C:Programme")
+        # No drive letters
+        self.assertRaises(TypeError, relative_filename_nt,
+                          r"\Programme\Python", r"\Programme")
+
+
+if __name__ == "__main__":
+    unittest.main()
+

Added: packages/thuban/branches/upstream/current/test/test_hittest.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_hittest.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_hittest.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,149 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Test Thuban.UI.hittest"""
+
+__version__ = "$Revision: 1589 $"
+# $Source$
+# $Id: test_hittest.py 1589 2003-08-15 12:49:08Z bh $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.UI.hittest import line_hit, polygon_hit, arc_hit
+
+
+class TestLineHit(unittest.TestCase):
+
+    def test_inside(self):
+        """Test line_hit with point that would be on the 'inside'
+
+        Inside here means that the point is to the right of the line but
+        not so close that the line itself is hit.
+        """
+        self.assertEquals(line_hit(0, 0, 10, 10, 20, 5), 1)
+        self.assertEquals(line_hit(10, 10, 0, 0, 20, 5), 1)
+        self.assertEquals(line_hit(10, 10, 0, 0, 8, 5), 1)
+
+    def test_outside(self):
+        """Test line_hit with point that would be on the 'outside'
+
+        Inside here means that the point is to the left of the line but
+        not so close that the line itself is hit.
+        """
+        self.assertEquals(line_hit(0, 0, 10, 10, -10, 5), 0)
+        self.assertEquals(line_hit(10, 10, 0, 0, -10, 5), 0)
+        self.assertEquals(line_hit(10, 10, 0, 0, 2, 5), 0)
+
+    def test_on_line(self):
+        """Test line_hit with point that would be on or near the line"""
+        self.assertEquals(line_hit(0, 0, 10, -10, 5, -5), -1)
+        self.assertEquals(line_hit(0, 0, 10, -10, 10, -10), -1)
+        self.assertEquals(line_hit(0, 0, 10, -10, 5, -6), -1)
+
+    def test_horizontal_line(self):
+        """Test line_hit with a horizontal line
+
+        For a horizonal line, line_hit will never return 1. It will
+        return -1 though for points close to or on the line.
+        """
+        self.assertEquals(line_hit(10, 10, 10, 10, -10, 10), 0)
+        self.assertEquals(line_hit(10, 10, 15, 10, 20, 10), 0)
+        self.assertEquals(line_hit(10, 10, 15, 10, 12, 10), -1)
+
+        # Hits near the line will also be counted as line hits.
+        self.assertEquals(line_hit(10, 10, 15, 10, 12, 11), -1)
+        self.assertEquals(line_hit(10, 10, 15, 10, 12, 9), -1)
+
+    def test_upper_ignored(self):
+        """Test line_hit with a point whose ray would hit the upper end point
+
+        The upper end point is not hit to avoid problems with hit
+        testing for polygons.
+        """
+        self.assertEquals(line_hit(-100, 20, 10, -10, 1000, 20), 0)
+        self.assertEquals(line_hit(10, -10, -100, 20, 1000, 20), 0)
+
+
+class TestPolygonHit(unittest.TestCase):
+
+    def test_simple_inside(self):
+        """Test polygon_hit with simple polygon and inside point"""
+        self.assertEquals(polygon_hit([[(0, 0), (10, 0), (10, 10), (0, 10),
+                                        (0, 0)]], 5, 5),
+                          1)
+
+    def test_simple_outside(self):
+        """Test polygon_hit with simple polygon and outside point"""
+        self.assertEquals(polygon_hit([[(0, 0), (10, 0), (10, 10), (0, 10),
+                                        (0, 0)]], 20, 5),
+                          0)
+        self.assertEquals(polygon_hit([[(0, 0), (10, 0), (10, 10), (0, 10),
+                                        (0, 0)]], 20, 100),
+                          0)
+
+        self.assertEquals(polygon_hit([[(0, 0), (10, 0), (10, 10), (0, 10),
+                                        (0, 0)]], 20, -10),
+                          0)
+
+    def test_holes_outside(self):
+        """Test polygon_hit with polygon with holes and outside point"""
+        points = [[(0, 0), (100, 0), (100, 100), (0, 100), (0, 0)],
+                  [(20, 20), (80, 20), (80, 80), (20, 80), (20, 20)]]
+        self.assertEquals(polygon_hit(points, 50, 50), 0)
+        self.assertEquals(polygon_hit(points, 130, 50), 0)
+
+    def test_holes_inside(self):
+        """Test polygon_hit with polygon with holes and inside point"""
+        points = [[(0, 0), (100, 0), (100, 100), (0, 100), (0, 0)],
+                  [(20, 20), (80, 20), (80, 80), (20, 80), (20, 20)]]
+        self.assertEquals(polygon_hit(points, 50, 90), 1)
+        self.assertEquals(polygon_hit(points, 90, 50), 1)
+        self.assertEquals(polygon_hit(points, 10, 50), 1)
+
+    def test_vertex(self):
+        """Test polygon_hit with simple polygon and point whose ray hits corner
+        """
+        points = [[(-10, -5), (-10, 20), (10, 50), (10, 0), (-10, -5)]]
+        self.assertEquals(polygon_hit(points, 0, 20), 1)
+
+    def test_border(self):
+        """Test polygon_hit with simple polygon and point on/near border"""
+        points = [[(-10, -5), (-10, 20), (10, 50), (10, 0), (-10, -5)]]
+        self.assertEquals(polygon_hit(points, -9, 20), -1)
+        self.assertEquals(polygon_hit(points, 0, -2), -1)
+        self.assertEquals(polygon_hit(points, 0, -4), -1)
+
+
+
+class TestArcHit(unittest.TestCase):
+
+    def test_simple_hit(self):
+        """Test arc_hit with simple arc and point on/near arc"""
+        self.assertEquals(arc_hit([[(0, 0), (10, 0), (10, 10), (20, 20)]],
+                                  5, 0), 1)
+        self.assertEquals(arc_hit([[(0, 0), (10, 0), (10, 10), (20, 20)]],
+                                  15, 16), 1)
+
+    def test_simple_not_hit(self):
+        """Test arc_hit with simple arc and point not on arc"""
+        self.assertEquals(arc_hit([[(0, 0), (10, 0), (10, 10), (20, 20)]],
+                                  5, 100), 0)
+        self.assertEquals(arc_hit([[(0, 0), (10, 0), (10, 10), (20, 20)]],
+                                  13, 7), 0)
+
+    def test_corner(self):
+        """Test arc_hit with point on/near arc's corner"""
+        self.assertEquals(arc_hit([[(0, 0), (10, 0), (10, 10), (20, 20)]],
+                                  11, 10), 1)
+        self.assertEquals(arc_hit([[(0, 0), (10, 0), (10, 10), (20, 20)]],
+                                  15, 10), 0)
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_label.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_label.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_label.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,93 @@
+# Copyright (c) 2002 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Label and LabelLayer classes
+"""
+
+__version__ = "$Revision: 330 $"
+# $Source$
+# $Id: test_label.py 330 2002-09-20 14:30:34Z bh $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.messages import CHANGED
+from Thuban.Model.label import Label, LabelLayer, \
+     ALIGN_CENTER, ALIGN_BASELINE, ALIGN_LEFT, ALIGN_TOP
+
+
+class TestLabel(unittest.TestCase):
+
+    """Test cases for the Label class"""
+
+    def test(self):
+        """Test Label"""
+        # The label objects are very simple. We just have to test
+        # whether instantiating one assigns the correct values to the
+        # instance variables
+        label = Label(10.5, 234567.0, "Label Text",
+                      ALIGN_CENTER, ALIGN_BASELINE)
+        self.assertEquals(label.x, 10.5)
+        self.assertEquals(label.y, 234567.0)
+        self.assertEquals(label.text, "Label Text")
+        self.assertEquals(label.halign, ALIGN_CENTER)
+        self.assertEquals(label.valign, ALIGN_BASELINE)
+
+
+class TestLabelLayer(unittest.TestCase, support.SubscriberMixin):
+
+    """Test cases for LabelLayer"""
+
+    def setUp(self):
+        """Clear the messages list and create a LabelLayer as self.layer
+        """
+        self.clear_messages()
+        self.layer = LabelLayer("A Label Layer")
+        self.layer.Subscribe(CHANGED, self.subscribe_with_params, CHANGED)
+
+    def tearDown(self):
+        """Clear the messages list and explictly destroy self.layer"""
+        self.layer.Destroy()
+        self.clear_messages()
+
+    def test_initial_state(self):
+        """Test LabelLayer's initial state"""
+        self.failIf(self.layer.WasModified())
+        self.assertEquals(self.layer.Title(), "A Label Layer")
+        self.assertEquals(self.layer.Labels(), [])
+        self.check_messages([])
+
+    def test_methods(self):
+        """Test LabelLayer methods"""
+        # first add a label
+        self.layer.AddLabel(10.5, 234567.0, "Label Text")
+        self.check_messages([(CHANGED,)])
+        self.assertEquals(self.layer.Labels()[0].text, "Label Text")
+        self.assert_(self.layer.WasModified())
+
+        # add another one
+        self.layer.AddLabel(-1000.125, 987654.0, "Another Label",
+                            ALIGN_LEFT, ALIGN_TOP)
+        self.check_messages([(CHANGED,),
+                             (CHANGED,)])
+        self.assertEquals(self.layer.Labels()[0].text, "Label Text")
+        self.assertEquals(self.layer.Labels()[1].text, "Another Label")
+
+        # remove one
+        self.layer.RemoveLabel(0)
+        self.check_messages([(CHANGED,),
+                             (CHANGED,),
+                             (CHANGED,)])
+        self.assertEquals(self.layer.Labels()[0].text, "Another Label")
+
+        
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/test/test_layer.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_layer.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_layer.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,536 @@
+# Copyright (c) 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Layer class
+"""
+
+__version__ = "$Revision: 2688 $"
+# $Source$
+# $Id: test_layer.py 2688 2006-06-30 12:27:20Z frank $
+
+import os
+import unittest
+
+import mockgeo
+import support
+support.initthuban()
+
+import shapelib
+import dbflib
+
+from Thuban.Model.session import Session
+from Thuban.Model.layer import BaseLayer, Layer, RasterLayer
+from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
+from Thuban.Model.messages import LAYER_LEGEND_CHANGED, \
+     LAYER_VISIBILITY_CHANGED, LAYER_SHAPESTORE_REPLACED, LAYER_CHANGED
+from Thuban.Model.table import FIELDTYPE_DOUBLE, FIELDTYPE_STRING, MemoryTable
+from Thuban.Model.proj import Projection
+from Thuban.Model.data import DerivedShapeStore
+from Thuban.Model.classification import Classification, ClassGroupSingleton, \
+     ClassGroupRange, ClassGroupPattern
+from Thuban.Model.color import Color
+
+import Thuban.Model.resource
+
+class TestLayer(unittest.TestCase, support.FileTestMixin,
+                support.FloatComparisonMixin):
+
+    """Test cases for different layer (shape) types"""
+
+    def setUp(self):
+        """Create a session self.session and initialize self.layer to None"""
+        self.session = Session("Test session for %s" % self.__class__)
+        self.layer = None
+
+    def tearDown(self):
+        """Call the layer's Destroy method and set session and layer to None"""
+        self.session.Destroy()
+        self.session = None
+        if self.layer is not None:
+            self.layer.Destroy()
+            self.layer = None
+
+    def build_path(self, filename):
+        return os.path.join("..", "Data", "iceland", filename)
+
+    def open_shapefile(self, filename):
+        """Open and return a shapestore for filename in the iceland data set"""
+        return self.session.OpenShapefile(self.build_path(filename))
+
+    def test_base_layer(self):
+        layer = self.layer = BaseLayer("Test BaseLayer")
+        self.assertEquals(layer.Title(), "Test BaseLayer")
+        self.failUnless(layer.Visible())
+
+        # toggle visibility
+        layer.SetVisible(False)
+        self.failIf(layer.Visible())
+
+        layer.SetVisible(True)
+        self.failUnless(layer.Visible())
+
+        self.failIf(layer.HasClassification())
+        self.failIf(layer.HasShapes())
+
+        self.assertEquals(layer.GetProjection(), None)
+
+        # set/get projection
+        proj = Projection(["proj=utm", "zone=26", "ellps=clrk66"])
+
+        layer.SetProjection(proj)
+        self.failUnless(layer.GetProjection() is proj)
+
+        # __init__ with other arguments
+        layer = BaseLayer("Test BaseLayer", False, proj)
+        self.failIf(layer.Visible())
+        self.failUnless(layer.GetProjection() is proj)
+
+    def test_arc_layer(self):
+        """Test Layer with arc shapes"""
+        layer = self.layer = Layer("Test Layer",
+                                   self.open_shapefile("roads-line.shp"))
+        self.failUnless(layer.HasClassification())
+        self.failUnless(layer.HasShapes())
+        self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
+        self.assertEquals(layer.NumShapes(), 839)
+        shape = layer.Shape(32)
+        self.assertPointListEquals(shape.Points(),
+                                   [[(-15.082174301147461, 66.27738189697265),
+                                     (-15.026350021362305, 66.27339172363281)]])
+        self.assertFloatSeqEqual(layer.BoundingBox(),
+                                 [-24.450359344482422, 63.426830291748047,
+                                  -13.55668830871582, 66.520111083984375])
+        shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
+        self.assertEquals([s.ShapeID() for s in shapes],
+                          [613, 726, 838])
+
+        self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]), 
+                          [-15.082174301147461, 66.27339172363281,
+                           -15.026350021362305, 66.27738189697265])
+
+        shape = layer.Shape(33)
+        self.assertPointListEquals(shape.Points(),
+                                   [[(-22.24850654602050, 66.30645751953125),
+                                     (-22.23273086547851, 66.29407501220703),
+                                     (-22.23158073425293,  66.2876892089843),
+                                     (-22.24631881713867, 66.27006530761718)]])
+
+        self.assertFloatSeqEqual(layer.ShapesBoundingBox([32, 33]), 
+                                 [-22.248506546020508, 66.270065307617188,
+                                  -15.026350021362305, 66.30645751953125])
+
+        self.assertEquals(layer.ShapesBoundingBox([]), None)
+        self.assertEquals(layer.ShapesBoundingBox(None), None)
+
+    def test_polygon_layer(self):
+        """Test Layer with polygon shapes"""
+        layer = self.layer = Layer("Test Layer",
+                                   self.open_shapefile("political.shp"))
+        self.failUnless(layer.HasClassification())
+        self.failUnless(layer.HasShapes())
+        self.assertEquals(layer.ShapeType(), SHAPETYPE_POLYGON)
+        self.assertEquals(layer.NumShapes(), 156)
+        shape = layer.Shape(4)
+        self.assertPointListEquals(shape.Points(),
+                                   [[(-22.40639114379882, 64.714111328125),
+                                     (-22.41621208190918, 64.7160034179687),
+                                     (-22.40605163574218, 64.719200134277),
+                                     (-22.40639114379882, 64.714111328125)]])
+        self.assertFloatSeqEqual(layer.BoundingBox(),
+                                 [-24.546524047851562, 63.286754608154297,
+                                  -13.495815277099609, 66.563774108886719])
+        shapes = layer.ShapesInRegion((-24.0, 64.0, -23.9, 64.1))
+        self.assertEquals([s.ShapeID() for s in shapes],
+                          [91, 92, 144, 146, 148, 150, 152, 153])
+
+    def test_point_layer(self):
+        """Test Layer with point shapes"""
+        layer = self.layer = Layer("Test Layer",
+                           self.open_shapefile("cultural_landmark-point.shp"))
+        self.failUnless(layer.HasClassification())
+        self.failUnless(layer.HasShapes())
+        self.assertEquals(layer.ShapeType(), SHAPETYPE_POINT)
+        self.assertEquals(layer.NumShapes(), 34)
+        shape = layer.Shape(0)
+        self.assertPointListEquals(shape.Points(),
+                                   [[(-22.711074829101562, 66.36572265625)]])
+        self.assertFloatSeqEqual(layer.BoundingBox(),
+                                 [-23.806047439575195, 63.405960083007812,
+                                  -15.12291431427002, 66.36572265625])
+        shapes = layer.ShapesInRegion((-24.0, 64.0, -23.80, 64.1))
+        self.assertEquals([s.ShapeID() for s in shapes],
+                          [0, 1, 2, 3, 4, 5, 27, 28, 29, 30, 31])
+
+    def test_arc_layer_with_projection(self):
+        """Test Layer with point shapes and a projection"""
+        # We use mock data here so that we have precise control over the
+        # values
+        table = MemoryTable([("FOO", FIELDTYPE_STRING)], [("bla",)])
+        store = mockgeo.SimpleShapeStore(SHAPETYPE_ARC,
+                              [[[(9884828.7209840547, 5607720.9774499247),
+                                 (11298336.04640449, 9287823.2044059951)]]],
+                                         table)
+        layer = self.layer = Layer("Test Layer", store)
+
+        proj = Projection(["proj=lcc", "lon_0=0", "lat_1=20n", "lat_2=60n",
+                           "ellps=clrk66"])
+        layer.SetProjection(proj)
+
+        self.assertFloatSeqEqual(layer.BoundingBox(),
+                                 (9884828.7209840547, 5607720.9774499247,
+                                  11298336.04640449, 9287823.2044059951))
+        self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
+                                 (90.0, -8.90043373, 120, 11.1616263))
+        shapes = layer.ShapesInRegion((100, -10, 150, +10))
+        self.assertEquals([s.ShapeID() for s in shapes], [0])
+        self.assertFloatSeqEqual(layer.ShapesBoundingBox([0]),
+                                 (90.0, -8.90043373, 120, 11.1616263))
+
+        # Test a very large bounding box in the query.  Naive inverse
+        # projection will create infs instead of proper coordinate
+        # values and a different result (an empty list instead of [0])
+        shapes = layer.ShapesInRegion((-180, -170, 200, +120))
+        self.assertEquals([s.ShapeID() for s in shapes],[0])
+
+    def test_empty_layer(self):
+        """Test Layer with empty shape file"""
+        # create an empty shape file
+        shapefilename = self.temp_file_name("layer_empty.shp")
+        shp = shapelib.create(shapefilename, shapelib.SHPT_POLYGON)
+        shp.close()
+        # create an empty DBF file too because Thuban can't cope yet
+        # with missing DBF file.
+        dbffilename = self.temp_file_name("layer_empty.dbf")
+        dbf = dbflib.create(dbffilename)
+        dbf.add_field("NAME", dbflib.FTString, 20, 0)
+        dbf.close()
+
+        # Now try to open it.
+        layer = self.layer = Layer("Empty Layer",
+                                   self.session.OpenShapefile(shapefilename))
+        self.assertEquals(layer.BoundingBox(), None)
+        self.assertEquals(layer.LatLongBoundingBox(), None)
+        self.assertEquals(layer.NumShapes(), 0)
+
+    def test_get_field_type(self):
+        """Test Layer.GetFieldType()"""
+        layer = self.layer = Layer("Test Layer",
+                                   self.open_shapefile("roads-line.shp"))
+        self.assertEquals(layer.GetFieldType("LENGTH"), FIELDTYPE_DOUBLE)
+        self.assertEquals(layer.GetFieldType("non existing"), None)
+
+    def test_raster_layer(self):
+        if not Thuban.Model.resource.has_gdal_support():
+            raise support.SkipTest("No gdal support")
+
+        filename = self.build_path("island.tif")
+        layer = RasterLayer("Test RasterLayer", filename)
+        self.failIf(layer.HasClassification())
+        self.failIf(layer.HasShapes())
+        self.assertEquals(layer.MaskType(), layer.MASK_BIT)
+        self.assertEquals(layer.GetImageFilename(), os.path.abspath(filename))
+        self.assertFloatSeqEqual(layer.BoundingBox(),
+                                 [-24.5500000, 63.2833330,
+                                  -13.4916670, 66.5666670])
+        self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
+                                 [-24.5500000, 63.2833330,
+                                  -13.4916670, 66.5666670])
+
+        info = layer.ImageInfo()
+        self.failIf(info is None)
+        self.failUnless(info.has_key("nBands"))
+        self.failUnless(info.has_key("Size"))
+        self.failUnless(info.has_key("Driver"))
+        self.failUnless(info.has_key("BandData"))
+
+        self.assertEquals(info["nBands"], 1)
+        self.assertEquals(info["Size"], (5002, 394))
+        self.assertEquals(info["Driver"], "GTiff")
+        self.assertEquals(info["BandData"], [(0.0, 140.0)])
+
+    def test_derived_store(self):
+        """Test layer with derived store"""
+        layer = self.layer = Layer("Test Layer",
+                                   self.open_shapefile("roads-line.shp"))
+        try:
+            store = layer.ShapeStore()
+            derived = DerivedShapeStore(store, store.Table())
+            layer.SetShapeStore(derived)
+            self.assert_(layer.ShapeStore() is derived)
+
+            self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
+            self.assertEquals(layer.NumShapes(), 839)
+            shape = layer.Shape(32)
+            self.assertPointListEquals(shape.Points(),
+                                       [[(-15.082174301147, 66.277381896972),
+                                         (-15.026350021362, 66.273391723632)]])
+            self.assertFloatSeqEqual(layer.BoundingBox(),
+                                     [-24.450359344482422, 63.426830291748047,
+                                      -13.55668830871582, 66.520111083984375])
+            shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
+            self.assertEquals([s.ShapeID() for s in shapes],
+                              [613, 726, 838])
+
+            self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
+                                     [-15.082174301147461, 66.27339172363281,
+                                      -15.026350021362305, 66.27738189697265])
+
+        finally:
+            store = derived = None
+
+
+class SetShapeStoreTests(unittest.TestCase, support.SubscriberMixin):
+
+    def setUp(self):
+        """Create a layer with a classification as self.layer"""
+        self.clear_messages()
+        self.session = Session("Test session for %s" % self.__class__)
+        self.shapefilename = os.path.join("..", "Data", "iceland",
+                                          "cultural_landmark-point.dbf")
+        self.store = self.session.OpenShapefile(self.shapefilename)
+        self.layer = Layer("test layer", self.store)
+        self.classification = Classification()
+        self.classification.AppendGroup(ClassGroupSingleton("FARM"))
+        self.layer.SetClassificationColumn("CLPTLABEL")
+        self.layer.SetClassification(self.classification)
+        self.layer.UnsetModified()
+        self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
+                             self.subscribe_with_params,
+                             LAYER_SHAPESTORE_REPLACED)
+        self.layer.Subscribe(LAYER_CHANGED,
+                             self.subscribe_with_params, LAYER_CHANGED)
+
+    def tearDown(self):
+        self.clear_messages()
+        self.layer.Destroy()
+        self.session.Destroy()
+        self.session = self.layer = self.store = self.classification = None
+
+    def test_sanity(self):
+        """SetShapeStoreTests sanity check
+
+        Test the initial state of the test case instances after setUp.
+        """
+        cls = self.layer.GetClassification()
+        self.assert_(cls is self.classification)
+        field = self.layer.GetClassificationColumn()
+        self.assertEquals(field, "CLPTLABEL")
+        self.assertEquals(self.layer.GetFieldType(field), FIELDTYPE_STRING)
+        self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
+        self.failIf(self.layer.WasModified())
+
+    def test_set_shape_store_modified_flag(self):
+        """Test whether Layer.SetShapeStore() sets the modified flag"""
+        memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
+                      [("bla",)] * self.layer.ShapeStore().Table().NumRows())
+        self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
+
+        self.assert_(self.layer.WasModified())
+
+    def test_set_shape_store_different_field_name(self):
+        """Test Layer.SetShapeStore() with different column name"""
+        memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
+                      [("bla",)] * self.layer.ShapeStore().Table().NumRows())
+        self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
+        # The classification should contain only the default group now.
+        self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
+        self.check_messages([(self.layer, LAYER_CHANGED),
+                             (self.layer, LAYER_SHAPESTORE_REPLACED)])
+
+    def test_set_shape_store_same_field(self):
+        """Test Layer.SetShapeStore() with same column name and type"""
+        memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
+                      [("bla",)] * self.layer.ShapeStore().Table().NumRows())
+        self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
+        # The classification should be the same as before
+        self.assert_(self.layer.GetClassification() is self.classification)
+        self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
+
+    def test_set_shape_store_same_field_different_type(self):
+        """Test Layer.SetShapeStore() with same column name but different type
+        """
+        memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
+                      [(0.0,)] * self.layer.ShapeStore().Table().NumRows())
+        self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
+        # The classification should contain only the default group now.
+        self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
+        self.check_messages([(self.layer, LAYER_CHANGED),
+                             (self.layer, LAYER_SHAPESTORE_REPLACED)])
+
+
+class TestLayerModification(unittest.TestCase, support.SubscriberMixin):
+
+    """Test cases for Layer method that modify the layer.
+    """
+
+    def setUp(self):
+        """Clear the list of received messages and create a layer and a session
+
+        The layer is bound to self.layer and the session to self.session.
+        """
+        self.clear_messages()
+        self.session = Session("Test session for %s" % self.__class__)
+        self.filename = os.path.join("..", "Data", "iceland", "political.shp")
+        self.layer = Layer("Test Layer",
+                           self.session.OpenShapefile(self.filename))
+        self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
+                             LAYER_LEGEND_CHANGED)
+        self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
+                             self.subscribe_with_params,
+                             LAYER_VISIBILITY_CHANGED)
+        self.layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
+                             LAYER_CHANGED)
+
+    def tearDown(self):
+        """Clear the list of received messages and explictly destroy self.layer
+        """
+        self.layer.Destroy()
+        self.layer = None
+        self.session.Destroy()
+        self.session = None
+        self.clear_messages()
+
+    def build_path(self, filename):
+        return os.path.join("..", "Data", "iceland", filename)
+
+    def test_sanity(self):
+        """TestLayerModification Sanity Checks"""
+        # test default settings
+        self.failIf(self.layer.WasModified())
+        self.assertEquals(self.layer.Visible(), 1)
+        # no messages should have been produced
+        self.check_messages([])
+
+    def test_visibility(self):
+        """Test Layer visibility"""
+        self.layer.SetVisible(0)
+        self.assertEquals(self.layer.Visible(), 0)
+        self.check_messages([(self.layer, LAYER_VISIBILITY_CHANGED)])
+
+        # currently, modifying the visibility doesn't count as changing
+        # the layer.
+        self.failIf(self.layer.WasModified())
+
+    def test_set_classification_numerical(self):
+        """Test Layer.SetClassification numerical"""
+        classification = Classification()
+        classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
+
+        self.layer.SetClassification(classification)
+        self.layer.SetClassificationColumn("AREA")
+
+        self.check_messages([(self.layer, LAYER_CHANGED),
+                             (self.layer, LAYER_CHANGED)])
+        self.failUnless(self.layer.WasModified())
+
+        self.clear_messages()
+        self.layer.UnsetModified()
+
+        # change only the classification column. This should issue a
+        # LAYER_CHANGED message as well.
+        self.layer.SetClassificationColumn("PERIMETER")
+
+        self.check_messages([(self.layer, LAYER_CHANGED)])
+        self.failUnless(self.layer.WasModified())
+
+    def test_set_classification_textual(self):
+        """Test Layer.SetClassification textual"""
+        classification = Classification()
+        classification.AppendGroup(ClassGroupPattern("I"))
+
+        self.layer.SetClassification(classification)
+        self.layer.SetClassificationColumn("POPYCOUN")
+
+        self.check_messages([(self.layer, LAYER_CHANGED),
+                             (self.layer, LAYER_CHANGED)])
+        self.failUnless(self.layer.WasModified())
+
+        self.clear_messages()
+        self.layer.UnsetModified()
+
+        # change only the classification column. This should issue a
+        # LAYER_CHANGED message as well.
+        self.layer.SetClassificationColumn("POPYREG")
+
+        self.check_messages([(self.layer, LAYER_CHANGED)])
+        self.failUnless(self.layer.WasModified())
+
+
+    def test_tree_info(self):
+        """Test Layer.TreeInfo"""
+        self.assertEquals(self.layer.TreeInfo(),
+                          ("Layer 'Test Layer'",
+                           ['Filename: %s' % os.path.abspath(self.filename),
+                            'Shown',
+                            'Shapes: 156',
+                   'Extent (lat-lon): (-24.5465, 63.2868, -13.4958, 66.5638)',
+                            'Shapetype: Polygon',
+                            self.layer.GetClassification()]))
+
+    def test_raster_layer(self):
+        if not Thuban.Model.resource.has_gdal_support():
+            raise support.SkipTest("No gdal support")
+
+
+        filename = self.build_path("island.tif")
+        layer = RasterLayer("Test RasterLayer", filename)
+
+        layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
+                        LAYER_CHANGED)
+
+        self.assertEquals(layer.MaskType(), layer.MASK_BIT)
+
+        layer.SetMaskType(layer.MASK_NONE)
+        self.failIf(layer.MaskType() != layer.MASK_NONE)
+        self.check_messages([(layer, LAYER_CHANGED)])
+        self.clear_messages()
+
+        layer.SetMaskType(layer.MASK_NONE)
+        self.failIf(layer.MaskType() != layer.MASK_NONE)
+        self.check_messages([])
+        self.clear_messages()
+
+        layer.SetMaskType(layer.MASK_BIT)
+        self.failIf(layer.MaskType() != layer.MASK_BIT)
+        self.check_messages([(layer, LAYER_CHANGED)])
+        self.clear_messages()
+
+        layer.SetMaskType(layer.MASK_BIT)
+        self.failIf(layer.MaskType() != layer.MASK_BIT)
+        self.check_messages([])
+        self.clear_messages()
+
+        layer.SetMaskType(layer.MASK_ALPHA)
+        self.failIf(layer.MaskType() != layer.MASK_ALPHA)
+
+        layer.SetOpacity(0)
+        self.assertEquals(layer.Opacity(), 0)
+        layer.SetOpacity(0.5)
+        self.assertEquals(layer.Opacity(), 0.5)
+
+        self.clear_messages()
+        layer.SetOpacity(1)
+        self.assertEquals(layer.Opacity(), 1)
+        self.check_messages([(layer, LAYER_CHANGED)])
+        self.clear_messages()
+
+        self.assertRaises(ValueError, layer.SetOpacity, -0.1)
+        self.assertRaises(ValueError, layer.SetOpacity, 1.1) 
+
+        layer.SetMaskType(layer.MASK_NONE)
+        self.clear_messages()
+        self.assertEquals(layer.Opacity(), 1)
+        self.check_messages([])
+        self.clear_messages()
+
+        self.assertRaises(ValueError, layer.SetMaskType, -1) 
+        self.assertRaises(ValueError, layer.SetMaskType, 4) 
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_lib_version.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_lib_version.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_lib_version.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,33 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+""""""
+
+__version__ = "$Revision: 2011 $"
+# $Source$
+# $Id: test_lib_version.py 2011 2003-12-03 09:46:27Z bh $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Lib.version import make_tuple
+
+
+class TestMakeTuple(unittest.TestCase):
+
+    def test(self):
+        """Test Thuban.version.make_tuple()"""
+        self.assertEquals(make_tuple("1.2"), (1, 2))
+        self.assertEquals(make_tuple("1.2.3"), (1, 2, 3))
+        self.assertEquals(make_tuple("2.4.0.7"), (2, 4, 0))
+        self.assertEquals(make_tuple("1.2+cvs.20031111"), (1, 2))
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_load.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_load.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_load.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,1161 @@
+# Copyright (c) 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test loading a thuban session from a file
+
+The tests in this file (test_load.py) are always be the tests for the
+current version of the thuban file format. Tests for older versions can
+be found in the version specific test modules, e.g. test_load_0_2 for
+files created by Thuban 0.2.
+
+Maintenance of the test cases:
+
+When during a development period the file format is changed with respect
+to the last released version for the first time, the tests here should
+be copied to the version specific test file.  The round-trip tests which
+save the session again and compare the XML files should not be copied
+over as they only make sense here to make sure th that the files checked
+here are actually ones that may have been written by the current thuban
+version.
+"""
+
+__version__ = "$Revision: 2688 $"
+# $Source$
+# $Id: test_load.py 2688 2006-06-30 12:27:20Z frank $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+import postgissupport
+from xmlsupport import sax_eventlist
+
+import dbflib
+import shapelib
+
+from Thuban import internal_from_unicode
+from Thuban.Model.save import save_session
+from Thuban.Model.load import load_session, parse_color, LoadError, \
+     LoadCancelled
+from Thuban.Model.color import Transparent
+from Thuban.Model.classification import ClassGroupProperties, ClassGroupRange,\
+    ClassGroupSingleton, ClassGroupPattern, ClassGroupDefault
+from Thuban.Model.postgisdb import ConnectionError
+from Thuban.Model.table import DBFTable, MemoryTable, \
+     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING, \
+     table_to_dbf
+from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
+     ALIGN_LEFT, ALIGN_RIGHT, ALIGN_BASELINE
+
+def filenames_equal(name1, name2):
+    """Return true if the filenames name1 and name2 are equal.
+
+    On systems where it is available, simply use os.path.samefile,
+    otherwise return whether the normalized versions of the filenames
+    according to os.path.normpath are equal.
+    """
+    if hasattr(os.path, "samefile"):
+        return os.path.samefile(name1, name2)
+    return os.path.normpath(name1) == os.path.normpath(name2)
+
+
+
+class LoadSessionTest(support.FileLoadTestCase):
+
+    """Base class for .thuban file loading tests
+
+    Basically the same as the FileLoadTestCase, except that all tests
+    use the '.thuban' extension by default and that setUp and tearDown
+    handle sessions.
+    """
+
+    file_extension = ".thuban"
+
+    def setUp(self):
+        """Create the test files"""
+        support.FileLoadTestCase.setUp(self)
+        self.session = None
+
+    def tearDown(self):
+        if self.session is not None:
+            self.session.Destroy()
+        self.session = None
+
+
+    dtd = "http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+    thubanids = [((dtd, n), (None, "id")) for n in
+                 ["fileshapesource", "filetable", "jointable",
+                  "derivedshapesource"]]
+    thubanidrefs = [((dtd, n), (None, m)) for n, m in
+                    [("layer", "shapestore"),
+                     ("jointable", "left"),
+                     ("jointable", "right"),
+                     ("derivedshapesource", "table"),
+                     ("derivedshapesource", "shapesource")]]
+
+    # The filenames in the tests should be understandable on all
+    # currently supported platforms so filenames is an empty list
+    filenames = []
+
+    del n, m, dtd
+
+    def check_format(self):
+        """Check whether the file we loaded from matches the one that
+        would be written. Call this from each test case after loading
+        the session
+        """
+        filename = self.temp_file_name(self.id() + ".roundtrip.thuban")
+        save_session(self.session, filename)
+        el1 = sax_eventlist(filename = filename, ids = self.thubanids,
+                            idrefs = self.thubanidrefs,
+                            filenames = self.filenames)
+        el2 = sax_eventlist(filename = self.filename(), ids = self.thubanids,
+                            idrefs = self.thubanidrefs,
+                            filenames = self.filenames)
+        if 0:
+            for a, b in zip(el1, el2):
+                print a != b and "***************" or ""
+                print a
+                print b
+
+        self.assertEquals(el1, el2,
+                          "loaded file not equivalent to the saved file")
+
+
+class ClassificationTest(LoadSessionTest):
+
+    """
+    Base class for tests that do some detailed checking of classifications
+    """
+
+    def TestLayers(self, layers, expected):
+        TITLE = 0
+        NUM_GROUPS = 1
+        CLASSES = 2
+        GROUP_TYPE = 0
+        GROUP_DATA = 1
+        GROUP_LABEL = 2
+        GROUP_PROPS = 3
+
+        eq = self.assertEquals
+
+        eq(len(layers), len(expected))
+
+        for layer, data in zip(layers, expected):
+            eq(layer.Title(), data[TITLE])
+
+            clazz = layer.GetClassification()
+            eq(clazz.GetNumGroups(), data[NUM_GROUPS])
+            eq(clazz.GetNumGroups() + 1, len(data[CLASSES]))
+
+            i = 0
+            for group in clazz:
+                props = ClassGroupProperties()
+                props.SetLineColor(
+                    parse_color(data[CLASSES][i][GROUP_PROPS][0]))
+                props.SetLineWidth(data[CLASSES][i][GROUP_PROPS][1])
+                props.SetFill(
+                    parse_color(data[CLASSES][i][GROUP_PROPS][2]))
+                if len(data[CLASSES][i][GROUP_PROPS]) > 3:
+                    props.SetSize(data[CLASSES][i][GROUP_PROPS][3])
+
+                if data[CLASSES][i][GROUP_TYPE] == "default":
+                    g = ClassGroupDefault(props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "range":
+                    g = ClassGroupRange((data[CLASSES][i][GROUP_DATA][0],
+                                         data[CLASSES][i][GROUP_DATA][1]),
+                                        props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "single":
+                    g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],
+                                          props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "pattern":
+                    g = ClassGroupPattern(data[CLASSES][i][GROUP_DATA],
+                                          props, data[CLASSES][i][GROUP_LABEL])
+
+                eq(group, g)
+
+                i += 1
+
+
+
+class TestSingleLayer(LoadSessionTest):
+
+    # Note: The use of &amp; and non-ascii characters is deliberate. We
+    # want to test whether the loading code handles that correctly.
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        title="Stra\xc3\x9fen &amp; Landmarken">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="\xc3\x9cbersicht">
+        <projection epsg="32627" name="WGS 84 / UTM zone 27N">
+            <parameter value="datum=WGS84"/>
+            <parameter value="ellps=WGS84"/>
+            <parameter value="proj=utm"/>
+            <parameter value="units=m"/>
+            <parameter value="zone=27"/>
+        </projection>
+        <layer shapestore="D1" visible="true" title="K\xc3\xbcste">
+            <classification>
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session with a single map with a single layer"""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        # Check the title
+        eq(session.Title(), internal_from_unicode(u"Stra\xdfen & Landmarken"))
+
+        # the session has one map.
+        maps = session.Maps()
+        eq(len(maps), 1)
+
+        # Check the map's attributes
+        map = maps[0]
+        eq(map.Title(), internal_from_unicode(u"\xdcbersicht"))
+        proj = map.GetProjection()
+        eq(proj.GetName(), "WGS 84 / UTM zone 27N")
+        eq(proj.EPSGCode(), "32627")
+        params = proj.GetAllParameters()
+        params.sort()
+        eq(params, ["datum=WGS84", "ellps=WGS84", "proj=utm", "units=m",
+                    "zone=27"])
+
+        # the map has a single layer
+        layers = map.Layers()
+        eq(len(layers), 1)
+
+        # Check the layer attributes
+        layer = layers[0]
+        eq(layer.Title(), internal_from_unicode(u"K\xfcste"))
+        self.failUnless(filenames_equal(layer.ShapeStore().FileName(),
+                                        os.path.join(self.temp_dir(),
+                                                     os.pardir, os.pardir,
+                                                     "Data", "iceland",
+                                                     "political.shp")))
+        eq(layer.GetClassification().GetDefaultFill(), Transparent)
+        eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")
+        eq(layer.Visible(), True)
+
+        self.check_format()
+
+        self.session.Destroy()
+        self.session = None
+
+    def test_leak(self):
+        """Test load_session for resource leaks
+
+        The load_session function had a resource leak in that it created
+        cyclic references. The objects would have been eventually
+        collected by the garbage collector but too late. One symptom is
+        that when layers are removed so that the last normal reference
+        owned indirectly by the session to a shape store goes away, the
+        shape store is not actually removed from the session even though
+        the session only keeps weak references because there are still
+        references owned by the cyclic garbage.
+        """
+        session = load_session(self.filename())
+        self.session = session
+
+        # sanity check
+        self.assertEquals(len(session.ShapeStores()), 1)
+
+        # remove the map. The shapestore should go away too
+        session.RemoveMap(session.Maps()[0])
+        self.assertEquals(len(session.ShapeStores()), 0)
+
+
+class TestNonAsciiColumnName(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        title="Non ASCII column name test">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="TestNonAsciiColumnName.shp"/>
+    <map title="map">
+        <projection name="Some Projection">
+            <parameter value="datum=WGS84"/>
+            <parameter value="ellps=WGS84"/>
+            <parameter value="proj=utm"/>
+            <parameter value="units=m"/>
+            <parameter value="zone=27"/>
+        </projection>
+        <layer shapestore="D1" visible="true" title="layer">
+            <classification field="Fl\xc3\xa4che" field_type="double">
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session with a single map with a single layer"""
+
+        # Create a shapefile and a dbffile with a non-ascii column name
+        dbffile = self.temp_file_name("TestNonAsciiColumnName.dbf")
+        shpfile = self.temp_file_name("TestNonAsciiColumnName.shp")
+        dbf = dbflib.create(dbffile)
+        dbf.add_field('Fl\xe4che', dbflib.FTDouble, 10, 5)
+        dbf.write_record(0, (0.0,))
+        dbf.close()
+        shp = shapelib.create(shpfile, shapelib.SHPT_POLYGON)
+        shp.write_object(-1, shapelib.SHPObject(shapelib.SHPT_POLYGON, 1,
+                                                [[(0,0), (10, 10), (10, 0),
+                                                  (0, 0)]]))
+        shp.close()
+
+        try:
+            session = load_session(self.filename())
+        except ValueError, v:
+            # Usually if the field name is not decoded properly the
+            # loading fails because the field type mentioned in the file
+            # is not None as returned from the layer for a non-existing
+            # column name so we check for that and report it as failure.
+            # Other exceptions are errors in the test case.
+            if str(v) == "xml field type differs from database!":
+                self.fail("Cannot load file with non-ascii column names")
+            else:
+                raise
+        self.session = session
+
+        # In case Thuban could load the file anyway (i.e. no ValueError
+        # exception in load_session()), check explicitly whether the
+        # field name was decoded properly. The test will probably lead
+        # to a UnicodeError instead of a test failure so we check that
+        # too
+        layer = session.Maps()[0].Layers()[0]
+        try:
+            self.assertEquals(layer.GetClassificationColumn(), 'Fl\xe4che')
+        except UnicodeError:
+            # FIXME: Obviously this will have to change if Thuban ever
+            # supports unicode properly.
+            self.fail("Column name was not converted to a bytestring")
+
+        # roundtrip check
+        self.check_format()
+
+
+class TestLayerVisibility(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="false" title="My Layer">
+            <classification>
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test that the visible flag is correctly loaded for a layer."""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+        maps = session.Maps()
+        eq(len(maps), 1)
+        map = maps[0]
+        layers = map.Layers()
+        eq(len(layers), 1)
+        layer = layers[0]
+
+        eq(layer.Visible(), False)
+
+        self.check_format()
+
+
+class TestSymbolSize(ClassificationTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="Thuban sample session">
+    <fileshapesource filetype="shapefile" id="D813968480" filename="../../Data/iceland/cultural_landmark-point.shp"/>
+    <map title="Iceland map">
+        <layer title="cultural_landmark-point" shapestore="D813968480" visible="true">
+            <classification field="CLPTLABEL" field_type="string">
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="1" size="3" fill="#000000"/>
+                </clnull>
+                <clpoint label="" value="RUINS">
+                    <cldata stroke="#000000" stroke_width="1" size="6" fill="#ffffff"/>
+                </clpoint>
+                <clpoint label="" value="FARM">
+                    <cldata stroke="#000000" stroke_width="1" size="9" fill="#ffff00"/>
+                </clpoint>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test that the size attribute for point symbols is correctly
+        loaded for a layer."""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        map = session.Maps()[0] # only one map in the sample
+
+        expected = [("cultural_landmark-point", 2,
+                        [("default", (), "",
+                            ("#000000", 1, "#000000", 3)),
+                         ("single", "RUINS", "",
+                            ("#000000", 1, "#ffffff", 6)),
+                         ("single", "FARM", "",
+                            ("#000000", 1, "#ffff00", 9))])]
+
+        self.TestLayers(map.Layers(), expected)
+
+        self.check_format()
+
+
+class TestClassification(ClassificationTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D138389860"
+        filename="../../Data/iceland/political.shp"/>
+    <fileshapesource filetype="shapefile" id="D138504492"
+        filename="../../Data/iceland/political.shp"/>
+    <fileshapesource filetype="shapefile" id="D123456789"
+        filename="../../Data/iceland/cultural_landmark-point.shp"/>
+    <map title="Test Map">
+        <projection name="">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D138389860" visible="true" title="My Layer">
+            <classification field="POPYREG" field_type="string">
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint label="" value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+                <clpoint label="" value="1">
+                    <cldata stroke="#000000" stroke_width="10" fill="None"/>
+                </clpoint>
+                <clpoint label="\xc3\x9cml\xc3\xa4uts"
+                        value="\xc3\xa4\xc3\xb6\xc3\xbc">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+        <layer shapestore="D138504492" visible="true" title="My Layer 2">
+            <classification field="AREA" field_type="double">
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clnull>
+                <clrange label="" range="[0;1[">
+                    <cldata stroke="#111111" stroke_width="1" fill="None"/>
+                </clrange>
+                <clpoint label="" value="0.5">
+                    <cldata stroke="#000000" stroke_width="1" fill="#111111"/>
+                </clpoint>
+                <clrange label="" range="[-1;0[">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clrange>
+                <clpoint label="" value="-0.5">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+        <layer shapestore="D123456789" visible="true" title="My Layer 3">
+            <classification field="CLPTLABEL" field_type="string">
+                <clnull label="">
+                    <cldata stroke="#000000" size="5" stroke_width="2" fill="None"/>
+                </clnull>
+                <clpoint label="" value="FARM">
+                    <cldata stroke="#111111" size="5" stroke_width="1" fill="None"/>
+                </clpoint>
+                <clpattern label="" pattern="BUI">
+                    <cldata stroke="#000000" size="5" stroke_width="1" fill="None"/>
+                </clpattern>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a Thuban session with a map and classified layers."""
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        expected = [("My Layer", 3,
+                        [("default", (), "",
+                            ("#000000", 1, "None")),
+                         ("single", "1", "",
+                            ("#000000", 2, "None")),
+                         ("single", "1", "",
+                            ("#000000", 10, "None")),
+                         ("single", internal_from_unicode(u"\xe4\xf6\xfc"),
+                          internal_from_unicode(u"\xdcml\xe4uts"),
+                            ("#000000", 1, "None"))]),
+                     ("My Layer 2", 4,
+                         [("default", (), "",
+                            ("#000000", 2, "None")),
+                          ("range", (0, 1), "",
+                            ("#111111", 1, "None")),
+                          ("single", .5, "",
+                            ("#000000", 1, "#111111")),
+                          ("range", (-1, 0), "",
+                            ("#000000", 1, "None")),
+                          ("single", -.5, "",
+                            ("#000000", 1, "None"))]),
+                     ("My Layer 3", 2,
+                         [("default", (), "",
+                            ("#000000", 2, "None")),
+                          ("single", "FARM", "",
+                            ("#111111", 1, "None")),
+                          ("pattern", "BUI", "",
+                            ("#000000", 1, "None"))]),
+                    ]
+
+        self.TestLayers(map.Layers(), expected)
+
+        self.check_format()
+
+
+class TestLabels(ClassificationTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true" title="My Layer">
+            <classification field="POPYREG" field_type="string">
+                <clnull label="hallo">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint label="welt" value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session and test for reading the group labels."""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        expected = [("My Layer", 1,
+                        [("default", (), "hallo",
+                            ("#000000", 1, "None")),
+                         ("single", "1", "welt",
+                            ("#000000", 2, "None"))])]
+
+        self.TestLayers(map.Layers(), expected)
+        self.check_format()
+
+
+class TestLayerProjection(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D2"
+        filename="../../Data/iceland/roads-line.shp"/>
+    <fileshapesource filetype="shapefile" id="D4"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D4" visible="true" title="My Layer">
+            <projection name="hello">
+                <parameter value="zone=13"/>
+                <parameter value="proj=tmerc"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+            <classification field="POPYREG" field_type="string">
+                <clnull label="hallo">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint label="welt" value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+        <layer shapestore="D2" visible="true" title="My Layer">
+            <projection name="Unknown">
+                <parameter value="proj=lcc"/>
+                <parameter value="lat_1=10"/>
+                <parameter value="lat_2=20"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+            <classification>
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test loading layers with projections"""
+        eq = self.assertEquals
+        neq = self.assertNotEqual
+
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        layers = map.Layers() # two layers in the sample
+
+        # test layer with a named projection
+        proj = layers[0].GetProjection()
+        neq(proj, None)
+        eq(proj.GetName(), "hello")
+        eq(proj.GetParameter("proj"), "tmerc")
+        eq(proj.GetParameter("zone"), "13")
+        eq(proj.GetParameter("ellps"), "clrk66")
+
+        # test layer with an unnamed projection
+        proj = layers[1].GetProjection()
+        neq(proj, None)
+        eq(proj.GetName(), "Unknown")
+        eq(proj.GetParameter("proj"), "lcc")
+        eq(proj.GetParameter("lat_1"), "10")
+        eq(proj.GetParameter("lat_2"), "20")
+        eq(proj.GetParameter("ellps"), "clrk66")
+
+        self.check_format()
+
+
+class TestRasterLayer(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        title="single map&amp;layer">
+    <map title="Test Map">
+        <rasterlayer visible="false" filename="../../Data/iceland/island.tif"
+                title="My RasterLayer" opacity="0.4" masktype="alpha"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        eq = self.assertEquals
+        neq = self.assertNotEqual
+
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        layer = map.Layers()[0] # one layer in the sample
+
+        eq(layer.Title(), "My RasterLayer")
+        eq(layer.Opacity(), 0.4)
+        eq(layer.MaskType(), layer.MASK_ALPHA)
+
+        self.failIf(layer.Visible())
+        self.failUnless(filenames_equal(layer.GetImageFilename(),
+                                        os.path.join(self.temp_dir(),
+                                                     os.pardir, os.pardir,
+                                                     "Data", "iceland",
+                                                     "island.tif")))
+        self.check_format()
+
+
+class TestJoinedTable(LoadSessionTest):
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="A Joined Table session">
+    <fileshapesource filetype="shapefile" id="D137227612"
+        filename="../../Data/iceland/roads-line.shp"/>
+    <filetable filetype="DBF" filename="load_joinedtable.dbf" id="D136171140"
+        title="Some Title"/>
+    <jointable id="D136169900" title="Joined"
+        right="D136171140" left="D137227612"
+        leftcolumn="RDLNTYPE" rightcolumn="RDTYPE"
+        jointype="LEFT OUTER"/>
+    <derivedshapesource table="D136169900" shapesource="D137227612"
+        id="D136170932"/>
+    <map title="Test Map">
+        <layer shapestore="D136170932" visible="true" title="My Layer">
+            <classification>
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def setUp(self):
+        """Extend inherited method to create the dbffile for the join"""
+        LoadSessionTest.setUp(self)
+        dbffile = self.temp_file_name("load_joinedtable.dbf")
+        dbf = dbflib.create(dbffile)
+        dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
+        dbf.add_field("TEXT", dbflib.FTString, 10, 0)
+        dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
+        dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
+        dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
+        dbf.close()
+
+    def test(self):
+        """Test loading a session containing a joined table"""
+        session = load_session(self.filename())
+        self.session = session
+
+        tables = session.Tables()
+        self.assertEquals(len(tables), 3)
+        # FIXME: The tests shouldn't assume a certain order of the tables
+        self.assertEquals(tables[0].Title(), "Some Title")
+        self.assertEquals(tables[1].Title(), "Joined")
+        self.assertEquals(tables[1].JoinType(), "LEFT OUTER")
+        self.check_format()
+
+
+class TestLabelLayer(LoadSessionTest):
+
+    # Note that the labels deliberately contain non-ascii characters to
+    # test whether they're supported correctly.
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="Thuban sample session">
+    <fileshapesource filetype="shapefile" id="D145265052"
+        filename="../../Data/iceland/political.shp"/>
+    <fileshapesource filetype="shapefile" id="D145412868"
+        filename="../../Data/iceland/cultural_landmark-point.shp"/>
+    <map title="Iceland map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D145265052" visible="true" title="political">
+            <projection name="Geographic">
+                <parameter value="proj=latlong"/>
+                <parameter value="to_meter=0.017453"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+            <classification>
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="1" fill="#c0c0c0"/>
+                </clnull>
+            </classification>
+        </layer>
+        <layer shapestore="D145412868" visible="true" title="landmarks">
+            <projection name="Geographic">
+                <parameter value="proj=latlong"/>
+                <parameter value="to_meter=0.017453"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+            <classification>
+                <clnull label="">
+                    <cldata size="5" stroke="#000000" stroke_width="1" fill="#ffff00"/>
+                </clnull>
+            </classification>
+        </layer>
+        <labellayer>
+            <label x="-21.5" y="64.25" text="RUINS"
+                halign="left" valign="center"/>
+            <label x="-15.125" y="64.75" text="H\xc3\xbctte"
+                halign="right" valign="top"/>
+        </labellayer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test loading a session with a label layer"""
+        session = load_session(self.filename())
+        self.session = session
+
+        label_layer = self.session.Maps()[0].LabelLayer()
+        expected_labels = [(-21.5, 64.25, "RUINS", ALIGN_LEFT, ALIGN_CENTER),
+                           (-15.125, 64.75, internal_from_unicode(u"H\xfctte"),
+                            ALIGN_RIGHT, ALIGN_TOP),
+                           ]
+        for label, values in zip(label_layer.Labels(), expected_labels):
+            self.assertEquals((label.x, label.y, label.text, label.halign,
+                               label.valign),
+                              values)
+        self.check_format()
+
+
+class TestPostGISLayer(LoadSessionTest):
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        title="unnamed session">
+    <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
+        dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
+    <dbshapesource id="D143149420" dbconn="D142684948"
+        tablename="landmarks_point_id" id_column="point_id"
+        geometry_column="the_geom" />
+    <map title="unnamed map">
+        <layer shapestore="D143149420" visible="true" stroke="#000000"
+                title="landmarks" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def setUp(self):
+        """Extend the inherited method to start the postgis server
+
+        Furthermore, patch the file contents with the real postgis db
+        information
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.postgisdb = self.server.get_default_static_data_db()
+
+        self.file_contents = self.__class__.file_contents % {
+            "dbname": self.postgisdb.dbname,
+            "user": self.server.user_name,
+            "port": self.server.port,
+            "host": self.server.host}
+        LoadSessionTest.setUp(self)
+
+    def test(self):
+        """Test loading a session containing a postgis shapestore"""
+        session = load_session(self.filename())
+        self.session = session
+        connections = session.DBConnections()
+        self.assertEquals(len(connections), 1)
+        conn = connections[0]
+        for attr, value in [("host", self.server.host),
+                            ("port", str(self.server.port)),
+                            ("user", self.server.user_name),
+                            ("dbname", self.postgisdb.dbname)]:
+            self.assertEquals(getattr(conn, attr), value)
+        layer = session.Maps()[0].Layers()[0]
+        self.failUnless(layer.ShapeStore().DBConnection() is conn)
+
+
+class TestPostGISLayerPassword(LoadSessionTest):
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        title="unnamed session">
+    <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
+        dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
+    <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
+    <map title="unnamed map">
+        <layer shapestore="D143149420" visible="true" stroke="#000000"
+                title="landmarks" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def setUp(self):
+        """Extend the inherited method to start the postgis server
+
+        Furthermore, patch the file contents with the real postgis db
+        information
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.postgisdb = self.server.get_default_static_data_db()
+
+        self.file_contents = self.__class__.file_contents % {
+            "dbname": self.postgisdb.dbname,
+            "user": self.server.user_name,
+            "port": self.server.port,
+            "host": self.server.host}
+        LoadSessionTest.setUp(self)
+
+        self.db_connection_callback_called = False
+        self.server.require_authentication(True)
+
+    def tearDown(self):
+        """Extend the inherited method to switch off postgresql authentication
+        """
+        self.server.require_authentication(False)
+        LoadSessionTest.tearDown(self)
+
+    def db_connection_callback(self, params, message):
+        """Implementation of Thuban.Model.hooks.query_db_connection_parameters
+        """
+        self.assertEquals(params,
+                          {"dbname": self.postgisdb.dbname,
+                           "user": self.server.user_name,
+                           "port": str(self.server.port),
+                           "host": self.server.host})
+        self.db_connection_callback_called = True
+        params = params.copy()
+        params["password"] = self.server.user_password
+        return params
+
+    def test_with_callback(self):
+        """Test loading a session with postgis, authentication and a callback
+        """
+        session = load_session(self.filename(),
+                      db_connection_callback = self.db_connection_callback)
+        self.session = session
+        connections = session.DBConnections()
+        self.assertEquals(len(connections), 1)
+        conn = connections[0]
+        for attr, value in [("host", self.server.host),
+                            ("port", str(self.server.port)),
+                            ("user", self.server.user_name),
+                            ("dbname", self.postgisdb.dbname)]:
+            self.assertEquals(getattr(conn, attr), value)
+        layer = session.Maps()[0].Layers()[0]
+        self.failUnless(layer.ShapeStore().DBConnection() is conn)
+        self.failUnless(self.db_connection_callback_called)
+
+    def test_without_callback(self):
+        """Test loading a session with postgis, authentication and no callback
+        """
+        # A password is required and there's no callback, so we should
+        # get a ConnectionError
+        self.assertRaises(ConnectionError, load_session, self.filename())
+
+    def test_cancel(self):
+        """Test loading a session with postgis and cancelling authentication
+        """
+        def cancel(*args):
+            self.db_connection_callback_called = True
+            return None
+
+        # If the user cancels, i.e. if the callbakc returns None, a
+        # LoadCancelled exception is raised.
+        self.assertRaises(LoadCancelled,
+                          load_session, self.filename(), cancel)
+        self.failUnless(self.db_connection_callback_called)
+
+
+class TestLoadError(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+        title="single map&amp;layer">
+    <fileshapesource id="D1" filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true"
+                stroke="#000000" title="My Layer" stroke_width="1"
+                fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test loading a session missing a required attribute"""
+        # Don't use assertRaises to make sure that if a session is
+        # actually returned it gets destroyed properly.
+        try:
+            self.session = load_session(self.filename())
+        except LoadError, value:
+            # Check the actual messge in value to make sure the
+            # LoadError really was about the missing attribute
+            self.assertEquals(str(value),
+              "Element "
+              "(u'http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd',"
+              " u'fileshapesource') requires an attribute 'filetype'")
+        else:
+            self.fail("Missing filetype attribute doesn't raise LoadError")
+
+class Shapefile_CallBack:
+
+    def __init__(self, params):
+        """Initialize the callback return values.
+           
+           params must be a dictionary of the potential CB modes (keys), 
+           with lists of tuples of return values as values.
+           Depending on the test the callback can be called multiple, 
+           each time a return value is poped from the list
+        """
+
+        self.params = params
+
+
+    def s_cb(self, filename, mode = None, second_try= 0):
+        if self.params.has_key(mode):
+            return self.params[mode].pop(0)
+        else:
+            raise LoadError
+        
+class TestAltPath(LoadSessionTest):
+
+    """Test the various cases in the alternative path feature.
+
+       The test checks the reasonable cases:
+       - First recognition of a path error, fixed with user interaction.
+       - First recognition of a path error, load cancelled.
+       - Path error fixed from list, confirmed by user.
+       - Path error fixed from list, changed by user.
+       - Path error fixed from list, cancelled by user.
+       - Path error wrongly fixed from list, manual fix forced.
+    """
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd" title="AltPath Test session">
+    <fileshapesource filetype="shapefile" id="D1108450956" filename="../../Data/iceland/political.shp"/>
+    <fileshapesource filetype="shapefile" id="D1108900076" filename="../Data/iceland/roads-line.shp"/>
+    <fileshapesource filetype="shapefile" id="D1108947244" filename="../../Data/iceland/cultural_landmark-point.shp"/>
+    <map title="not the iceland map">
+        <layer title="political" stroke_width="1" shapestore="D1108450956" visible="true" stroke="#000000" fill="#c0c0c0"/>
+        <layer title="roads-line" stroke_width="1" shapestore="D1108900076" visible="true" stroke="#000000" fill="None"/>
+        <layer title="something else" stroke_width="1" shapestore="D1108947244" visible="true" stroke="#000000" fill="None"/>
+    </map>
+</session>
+'''
+
+    def checkSession(self, session):
+        """Check if session has been loaded successfully."""
+        
+        eq = self.assertEquals
+
+        map = session.Maps()[0]
+        layers = map.Layers()
+
+        eq("AltPath Test session", session.Title())
+        eq("not the iceland map", map.Title())
+        eq(3,len(layers))
+        eq("political",layers[0].Title())
+        eq("roads-line",layers[1].Title())
+        eq("something else",layers[2].Title())
+
+    def test_01_single_path_error_fix(self):
+        """Test single file path error fix."""
+        # The usual initial case
+        s_cb = Shapefile_CallBack({
+                    "search": [("../Data/iceland/roads-line.shp",0)], 
+                    "check": [(None, None)]})
+        self.session = load_session(self.filename(), 
+                                    shapefile_callback =s_cb.s_cb)
+        self.checkSession(self.session)
+        
+    def test_02_path_error_fix_from_list(self):
+        """Test single file path error fix."""
+        # This represents the usual case for "from_list" 
+        s_cb = Shapefile_CallBack({
+                "search": [("../Data/iceland/roads-line.shp",1)], 
+                "check": [(os.path.abspath("../Data/iceland/roads-line.shp"),1)]
+               })
+        self.session = load_session(self.filename(), 
+                                    shapefile_callback =s_cb.s_cb)
+        self.checkSession(self.session)
+
+    def test_03_single_path_error_cancelled(self):
+        """Test alternative path cancelled."""
+        s_cb = Shapefile_CallBack({
+                    "search": [(None,0)], 
+                    "check": [(None, None)]})
+        self.assertRaises(LoadCancelled, 
+                            load_session, self.filename(), None, s_cb.s_cb)
+
+    def test_04_path_error_fix_from_list_cancelled(self):
+        """Test alternative path from list cancelled."""
+        s_cb = Shapefile_CallBack({
+                "search": [("../Data/iceland/roads-line.shp",1)], 
+                "check": [(None,1)]
+               })
+        self.assertRaises(LoadCancelled, 
+                            load_session, self.filename(), None, s_cb.s_cb)
+
+    def test_05_path_error_fix_from_list_changed(self):
+        """Test alternative path from list changed."""
+        s_cb = Shapefile_CallBack({
+                "search": [("../Data/iceland/roads-line.shp",1)], 
+                "check": [("../Data/iceland/roads-line.shp",0)]
+               })
+        self.session = load_session(self.filename(), 
+                                    shapefile_callback =s_cb.s_cb)
+        self.checkSession(self.session)
+
+    def test_06_path_error_fix_from_list_fails(self):
+        """Test alternative path recovery from list."""
+        s_cb = Shapefile_CallBack({
+                "search": [("../wrong/iceland/roads-line.shp",1),
+                            ("../Data/iceland/roads-line.shp",0)], 
+                "check": [(None,None)]
+               })
+        self.session = load_session(self.filename(), 
+                                    shapefile_callback =s_cb.s_cb)
+        self.assertRaises(IndexError, 
+                            s_cb.s_cb, None, "search")
+        
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_load_0_2.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_load_0_2.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_load_0_2.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,252 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test loading a thuban session from a files generated by Thuban 0.2 and earlier
+"""
+
+__version__ = "$Revision: 1357 $"
+# $Source$
+# $Id: test_load_0_2.py 1357 2003-07-02 09:38:27Z jonathan $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.load import load_session, parse_color
+from Thuban.Model.color import Transparent
+from Thuban.Model.classification import ClassGroupProperties, ClassGroupRange,\
+    ClassGroupSingleton, ClassGroupDefault
+
+
+def filenames_equal(name1, name2):
+    """Return true if the filenames name1 and name2 are equal.
+
+    On systems where it is available, simply use os.path.samefile,
+    otherwise return whether the normalized versions of the filenames
+    according to os.path.normpath are equal.
+    """
+    if hasattr(os.path, "samefile"):
+        return os.path.samefile(name1, name2)
+    return os.path.normpath(name1) == os.path.normpath(name2)
+
+
+
+class LoadSessionTest(support.FileLoadTestCase):
+
+    """Base class for .thuban file loading tests
+
+    Basically the same as the FileLoadTestCase, except that all tests
+    use the '.thuban' extension by default and that setUp and tearDown
+    handle sessions.
+    """
+
+    file_extension = ".thuban"
+
+    def setUp(self):
+        """Create the test files"""
+        support.FileLoadTestCase.setUp(self)
+        self.session = None
+
+    def tearDown(self):
+        if self.session is not None:
+            self.session.Destroy()
+        self.session = None
+
+
+class ClassificationTest(LoadSessionTest):
+
+    """
+    Base class for tests that do some detailed checking of classifications
+    """
+
+    def TestLayers(self, layers, expected):
+        TITLE = 0
+        NUM_GROUPS = 1
+        CLASSES = 2
+        GROUP_TYPE = 0
+        GROUP_DATA = 1
+        GROUP_LABEL = 2
+        GROUP_PROPS = 3
+
+        eq = self.assertEquals
+
+        eq(len(layers), len(expected))
+
+        for layer, data in zip(layers, expected):
+            eq(layer.Title(), data[TITLE])
+
+            clazz = layer.GetClassification()
+            eq(clazz.GetNumGroups(), data[NUM_GROUPS])
+            eq(clazz.GetNumGroups() + 1, len(data[CLASSES]))
+
+            i = 0
+            for group in clazz:
+                props = ClassGroupProperties()
+                props.SetLineColor(
+                    parse_color(data[CLASSES][i][GROUP_PROPS][0]))
+                props.SetLineWidth(data[CLASSES][i][GROUP_PROPS][1])
+                props.SetFill(
+                    parse_color(data[CLASSES][i][GROUP_PROPS][2]))
+
+                if data[CLASSES][i][GROUP_TYPE] == "default":
+                    g = ClassGroupDefault(props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "range":
+                    g = ClassGroupRange((data[CLASSES][i][GROUP_DATA][0],
+                                         data[CLASSES][i][GROUP_DATA][1]),
+                                        props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "single":
+                    g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],
+                                          props, data[CLASSES][i][GROUP_LABEL])
+
+                eq(group, g)
+
+                i += 1
+
+
+
+class TestSingleLayer(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban.dtd">
+<session title="single map&amp;layer">
+	<map title="Test Map">
+		<projection>
+			<parameter value="zone=26"/>
+			<parameter value="proj=utm"/>
+			<parameter value="ellps=clrk66"/>
+		</projection>
+		<layer title="My Layer" stroke_width="1" fill="None"
+                    filename="../../Data/iceland/political.shp"
+                    stroke="#000000"/>
+	</map>
+</session>
+'''
+
+    def test(self):
+        """Load a Thuban 0.2 session with a single map with a single layer"""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        # Check the title
+        eq(session.Title(), "single map&layer")
+
+        # the session has one map.
+        maps = session.Maps()
+        eq(len(maps), 1)
+
+        # Check the map's attributes
+        map = maps[0]
+        eq(map.Title(), "Test Map")
+
+        # the map has a single layer
+        layers = map.Layers()
+        eq(len(layers), 1)
+
+        # Check the layer attributes
+        layer = layers[0]
+        eq(layer.Title(), "My Layer")
+        self.failUnless(filenames_equal(layer.ShapeStore().FileName(),
+                                        os.path.join(self.temp_dir(),
+                                                     os.pardir, os.pardir,
+                                                     "Data", "iceland",
+                                                     "political.shp")))
+        eq(layer.GetClassification().GetDefaultFill(), Transparent)
+        eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")
+        eq(layer.Visible(), True)
+
+        self.session.Destroy()
+        self.session = None
+
+
+class TestClassification(ClassificationTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban.dtd">
+<session title="single map&amp;layer">
+	<map title="Test Map">
+		<projection>
+			<parameter value="zone=26"/>
+			<parameter value="proj=utm"/>
+			<parameter value="ellps=clrk66"/>
+		</projection>
+		<layer title="My Layer" stroke_width="1" fill="None"
+                    filename="../../Data/iceland/political.shp"
+                    stroke="#000000">
+            <classification field="POPYREG" field_type="string">
+                <clnull>
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+                <clpoint value="1">
+                    <cldata stroke="#000000" stroke_width="10" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+		<layer title="My Layer 2" stroke_width="1" fill="None"
+                    filename="../../Data/iceland/political.shp"
+                    stroke="#000000">
+            <classification field="AREA" field_type="double">
+                <clnull>
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clnull>
+                <clrange min="0" max="1">
+                    <cldata stroke="#111111" stroke_width="1" fill="None"/>
+                </clrange>
+                <clpoint value=".5">
+                    <cldata stroke="#000000" stroke_width="1" fill="#111111"/>
+                </clpoint>
+                <clrange min="-1" max="0">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clrange>
+                <clpoint value="-.5">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+	</map>
+</session>
+'''
+
+    def test(self):
+        """Load a Thuban 0.2 session with a map and classified layers."""
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        expected = [("My Layer", 2,
+                        [("default", (), "",
+                            ("#000000", 1, "None")),
+                         ("single", "1", "",
+                            ("#000000", 2, "None")),
+                         ("single", "1", "",
+                            ("#000000", 10, "None"))]),
+                     ("My Layer 2", 4,
+                         [("default", (), "",
+                            ("#000000", 2, "None")),
+                          ("range", (0, 1), "",
+                            ("#111111", 1, "None")),
+                          ("single", .5, "",
+                            ("#000000", 1, "#111111")),
+                          ("range", (-1, 0), "",
+                            ("#000000", 1, "None")),
+                          ("single", -.5, "",
+                            ("#000000", 1, "None"))])]
+
+        self.TestLayers(map.Layers(), expected)
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/test/test_load_0_8.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_load_0_8.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_load_0_8.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,592 @@
+# Copyright (c) 2002, 2003, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test loading a thuban session from a file generated by Thuban 0.8.0 or 0.8.1
+"""
+
+__version__ = "$Revision: 2642 $"
+# $Source$
+# $Id: test_load_0_8.py 2642 2005-07-01 20:49:04Z bh $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+import dbflib
+
+from Thuban import internal_from_unicode
+from Thuban.Model.load import load_session, parse_color, LoadError
+from Thuban.Model.color import Transparent
+from Thuban.Model.classification import ClassGroupProperties, ClassGroupRange,\
+    ClassGroupSingleton, ClassGroupDefault
+
+
+def filenames_equal(name1, name2):
+    """Return true if the filenames name1 and name2 are equal.
+
+    On systems where it is available, simply use os.path.samefile,
+    otherwise return whether the normalized versions of the filenames
+    according to os.path.normpath are equal.
+    """
+    if hasattr(os.path, "samefile"):
+        return os.path.samefile(name1, name2)
+    return os.path.normpath(name1) == os.path.normpath(name2)
+
+
+
+class LoadSessionTest(support.FileLoadTestCase):
+
+    """Base class for .thuban file loading tests
+
+    Basically the same as the FileLoadTestCase, except that all tests
+    use the '.thuban' extension by default and that setUp and tearDown
+    handle sessions.
+    """
+
+    file_extension = ".thuban"
+
+    def setUp(self):
+        """Create the test files"""
+        support.FileLoadTestCase.setUp(self)
+        self.session = None
+
+    def tearDown(self):
+        if self.session is not None:
+            self.session.Destroy()
+        self.session = None
+
+
+    dtd = "http://thuban.intevation.org/dtds/thuban-0.8.dtd"
+    thubanids = [((dtd, n), (None, "id")) for n in
+                 ["fileshapesource", "filetable", "jointable",
+                  "derivedshapesource"]]
+    thubanidrefs = [((dtd, n), (None, m)) for n, m in
+                    [("layer", "shapestore"),
+                     ("jointable", "left"),
+                     ("jointable", "right"),
+                     ("derivedshapesource", "table"),
+                     ("derivedshapesource", "shapesource")]]
+    del n, m, dtd
+
+
+class ClassificationTest(LoadSessionTest):
+
+    """
+    Base class for tests that do some detailed checking of classifications
+    """
+
+    def TestLayers(self, layers, expected):
+        TITLE = 0
+        NUM_GROUPS = 1
+        CLASSES = 2
+        GROUP_TYPE = 0
+        GROUP_DATA = 1
+        GROUP_LABEL = 2
+        GROUP_PROPS = 3
+
+        eq = self.assertEquals
+
+        eq(len(layers), len(expected))
+
+        for layer, data in zip(layers, expected):
+            eq(layer.Title(), data[TITLE])
+
+            clazz = layer.GetClassification()
+            eq(clazz.GetNumGroups(), data[NUM_GROUPS])
+            eq(clazz.GetNumGroups() + 1, len(data[CLASSES]))
+
+            i = 0
+            for group in clazz:
+                props = ClassGroupProperties()
+                props.SetLineColor(
+                    parse_color(data[CLASSES][i][GROUP_PROPS][0]))
+                props.SetLineWidth(data[CLASSES][i][GROUP_PROPS][1])
+                props.SetFill(
+                    parse_color(data[CLASSES][i][GROUP_PROPS][2]))
+
+                if data[CLASSES][i][GROUP_TYPE] == "default":
+                    g = ClassGroupDefault(props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "range":
+                    g = ClassGroupRange((data[CLASSES][i][GROUP_DATA][0],
+                                         data[CLASSES][i][GROUP_DATA][1]),
+                                        props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "single":
+                    g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],
+                                          props, data[CLASSES][i][GROUP_LABEL])
+
+                eq(group, g)
+
+                i += 1
+
+
+
+class TestSingleLayer(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.8.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true"
+                stroke="#000000" title="My Layer" stroke_width="1"
+                fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session with a single map with a single layer"""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        # Check the title
+        eq(session.Title(), "single map&layer")
+
+        # the session has one map.
+        maps = session.Maps()
+        eq(len(maps), 1)
+
+        # Check the map's attributes
+        map = maps[0]
+        eq(map.Title(), "Test Map")
+
+        # the map has a single layer
+        layers = map.Layers()
+        eq(len(layers), 1)
+
+        # Check the layer attributes
+        layer = layers[0]
+        eq(layer.Title(), "My Layer")
+        self.failUnless(filenames_equal(layer.ShapeStore().FileName(),
+                                        os.path.join(self.temp_dir(),
+                                                     os.pardir, os.pardir,
+                                                     "Data", "iceland",
+                                                     "political.shp")))
+        eq(layer.GetClassification().GetDefaultFill(), Transparent)
+        eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")
+        eq(layer.Visible(), True)
+
+        self.session.Destroy()
+        self.session = None
+
+
+class TestLayerVisibility(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.8.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="false" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test that the visible flag is correctly loaded for a layer."""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+        maps = session.Maps()
+        eq(len(maps), 1)
+        map = maps[0]
+        layers = map.Layers()
+        eq(len(layers), 1)
+        layer = layers[0]
+
+        eq(layer.Visible(), False)
+
+
+class TestClassification(ClassificationTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban.dtd">
+<session title="single map&amp;layer">
+	<map title="Test Map">
+		<projection>
+			<parameter value="zone=26"/>
+			<parameter value="proj=utm"/>
+			<parameter value="ellps=clrk66"/>
+		</projection>
+		<layer title="My Layer" stroke_width="1" fill="None"
+                    filename="../../Data/iceland/political.shp"
+                    stroke="#000000">
+            <classification field="POPYREG" field_type="string">
+                <clnull>
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+                <clpoint value="1">
+                    <cldata stroke="#000000" stroke_width="10" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+		<layer title="My Layer 2" stroke_width="1" fill="None"
+                    filename="../../Data/iceland/political.shp"
+                    stroke="#000000">
+            <classification field="AREA" field_type="double">
+                <clnull>
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clnull>
+                <clrange min="0" max="1">
+                    <cldata stroke="#111111" stroke_width="1" fill="None"/>
+                </clrange>
+                <clpoint value=".5">
+                    <cldata stroke="#000000" stroke_width="1" fill="#111111"/>
+                </clpoint>
+                <clrange min="-1" max="0">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clrange>
+                <clpoint value="-.5">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+	</map>
+</session>
+'''
+
+    def test(self):
+        """Load a Thuban session with a map and classified layers."""
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        expected = [("My Layer", 2,
+                        [("default", (), "",
+                            ("#000000", 1, "None")),
+                         ("single", "1", "",
+                            ("#000000", 2, "None")),
+                         ("single", "1", "",
+                            ("#000000", 10, "None"))]),
+                     ("My Layer 2", 4,
+                         [("default", (), "",
+                            ("#000000", 2, "None")),
+                          ("range", (0, 1), "",
+                            ("#111111", 1, "None")),
+                          ("single", .5, "",
+                            ("#000000", 1, "#111111")),
+                          ("range", (-1, 0), "",
+                            ("#000000", 1, "None")),
+                          ("single", -.5, "",
+                            ("#000000", 1, "None"))])]
+
+        self.TestLayers(map.Layers(), expected)
+
+
+class TestLabels(ClassificationTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.8.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None">
+            <classification field="POPYREG" field_type="string">
+                <clnull label="hallo">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint label="welt" value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session and test for reading the group labels."""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        expected = [("My Layer", 1,
+                        [("default", (), "hallo",
+                            ("#000000", 1, "None")),
+                         ("single", "1", "welt",
+                            ("#000000", 2, "None"))])]
+
+        self.TestLayers(map.Layers(), expected)
+
+
+class TestLayerProjection(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.8.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D2"
+        filename="../../Data/iceland/roads-line.shp"/>
+    <fileshapesource filetype="shapefile" id="D4"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D4" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None">
+            <projection name="hello">
+                <parameter value="zone=13"/>
+                <parameter value="proj=tmerc"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+            <classification field="POPYREG" field_type="string">
+                <clnull label="hallo">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint label="welt" value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+        <layer shapestore="D2" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None">
+            <projection name="Unknown">
+                <parameter value="proj=lcc"/>
+                <parameter value="lat_1=10"/>
+                <parameter value="lat_2=20"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test loading layers with projections"""
+        eq = self.assertEquals
+        neq = self.assertNotEqual
+
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        layers = map.Layers() # two layers in the sample
+
+        # test layer with a named projection
+        proj = layers[0].GetProjection()
+        neq(proj, None)
+        eq(proj.GetName(), "hello")
+        eq(proj.GetParameter("proj"), "tmerc")
+        eq(proj.GetParameter("zone"), "13")
+        eq(proj.GetParameter("ellps"), "clrk66")
+
+        # test layer with an unnamed projection
+        proj = layers[1].GetProjection()
+        neq(proj, None)
+        eq(proj.GetName(), "Unknown")
+        eq(proj.GetParameter("proj"), "lcc")
+        eq(proj.GetParameter("lat_1"), "10")
+        eq(proj.GetParameter("lat_2"), "20")
+        eq(proj.GetParameter("ellps"), "clrk66")
+
+
+class TestRasterLayer(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.8.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd"
+        title="single map&amp;layer">
+    <map title="Test Map">
+        <rasterlayer visible="false" filename="../../Data/iceland/island.tif"
+                title="My RasterLayer"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        eq = self.assertEquals
+        neq = self.assertNotEqual
+
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        layer = map.Layers()[0] # one layer in the sample
+
+        eq(layer.Title(), "My RasterLayer")
+        self.failIf(layer.Visible())
+        self.failUnless(filenames_equal(layer.GetImageFilename(),
+                                        os.path.join(self.temp_dir(),
+                                                     os.pardir, os.pardir,
+                                                     "Data", "iceland",
+                                                     "island.tif")))
+
+class TestJoinedTable(LoadSessionTest):
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.8.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd" title="A Joined Table session">
+    <fileshapesource filetype="shapefile" id="D137227612"
+        filename="../../Data/iceland/roads-line.shp"/>
+    <filetable filetype="DBF" filename="load_joinedtable.dbf" id="D136171140"
+        title="Some Title"/>
+    <jointable leftcolumn="RDLNTYPE" right="D136171140"
+        title="Joined" rightcolumn="RDTYPE" id="D136169900" left="D137227612"/>
+    <derivedshapesource table="D136169900" shapesource="D137227612"
+        id="D136170932"/>
+    <map title="Test Map">
+        <layer shapestore="D136170932" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def setUp(self):
+        """Extend inherited method to create the dbffile for the join"""
+        LoadSessionTest.setUp(self)
+        dbffile = self.temp_file_name("load_joinedtable.dbf")
+        dbf = dbflib.create(dbffile)
+        dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
+        dbf.add_field("TEXT", dbflib.FTString, 10, 0)
+        dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
+        dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
+        dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
+        dbf.close()
+
+    def test(self):
+        """Test loading a session containing a joined table"""
+        session = load_session(self.filename())
+        self.session = session
+
+        tables = session.Tables()
+        self.assertEquals(len(tables), 3)
+        # FIXME: The tests shouldn't assume a certain order of the tables
+        self.assertEquals(tables[0].Title(), "Some Title")
+        self.assertEquals(tables[1].Title(), "Joined")
+        self.assertEquals(tables[1].JoinType(), "INNER")
+
+
+class TestLoadError(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.8.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd"
+        title="single map&amp;layer">
+    <fileshapesource id="D1" filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true"
+                stroke="#000000" title="My Layer" stroke_width="1"
+                fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test loading a session missing a required attribute"""
+        # Don't use assertRaises to make sure that if a session is
+        # actually returned it gets destroyed properly.
+        try:
+            self.session = load_session(self.filename())
+        except LoadError, value:
+            pass
+        else:
+            self.fail("Missing filetype attribute doesn't raise LoadError")
+
+
+class TestUnicodeStrings(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.8.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.8.dtd"
+        title="Frida: Free Vector Geodata Osnabr\xc3\xbcck">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Osnabr\xc3\xbcck">
+        <projection name="Osnabr\xc3\xbcck Projection">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true"
+                stroke="#000000" title="Osnabr\xc3\xbcck Layer"
+                stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session with unicode strings"""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        # Check the title
+        eq(session.Title(),
+           internal_from_unicode(u"Frida: Free Vector Geodata Osnabr\xfcck"))
+
+        # Check the map's title
+        maps = session.Maps()
+        map = maps[0]
+        eq(map.Title(), internal_from_unicode(u"Osnabr\xfcck"))
+
+        # Check the layer's title
+        layers = map.Layers()
+        layer = layers[0]
+        eq(layer.Title(), internal_from_unicode(u"Osnabr\xfcck Layer"))
+
+        # Check the projection's title
+        projection = map.GetProjection()
+        eq(projection.GetName(),
+           internal_from_unicode(u"Osnabr\xfcck Projection"))
+
+        self.session.Destroy()
+        self.session = None
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/test/test_load_0_9.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_load_0_9.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_load_0_9.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,714 @@
+# Copyright (c) 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test loading a thuban session from a file written by Thuban 0.9.
+
+See test_load.py for how the various test_load*.py files relate to each other.
+"""
+
+__version__ = "$Revision: 2642 $"
+# $Source$
+# $Id: test_load_0_9.py 2642 2005-07-01 20:49:04Z bh $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+import postgissupport
+from xmlsupport import sax_eventlist
+
+import dbflib
+
+from Thuban import internal_from_unicode
+from Thuban.Model.save import save_session
+from Thuban.Model.load import load_session, parse_color, LoadError, \
+     LoadCancelled
+from Thuban.Model.color import Transparent
+from Thuban.Model.classification import ClassGroupProperties, ClassGroupRange,\
+    ClassGroupSingleton, ClassGroupDefault
+from Thuban.Model.postgisdb import ConnectionError
+
+def filenames_equal(name1, name2):
+    """Return true if the filenames name1 and name2 are equal.
+
+    On systems where it is available, simply use os.path.samefile,
+    otherwise return whether the normalized versions of the filenames
+    according to os.path.normpath are equal.
+    """
+    if hasattr(os.path, "samefile"):
+        return os.path.samefile(name1, name2)
+    return os.path.normpath(name1) == os.path.normpath(name2)
+
+
+
+class LoadSessionTest(support.FileLoadTestCase):
+
+    """Base class for .thuban file loading tests
+
+    Basically the same as the FileLoadTestCase, except that all tests
+    use the '.thuban' extension by default and that setUp and tearDown
+    handle sessions.
+    """
+
+    file_extension = ".thuban"
+
+    def setUp(self):
+        """Create the test files"""
+        support.FileLoadTestCase.setUp(self)
+        self.session = None
+
+    def tearDown(self):
+        if self.session is not None:
+            self.session.Destroy()
+        self.session = None
+
+
+    dtd = "http://thuban.intevation.org/dtds/thuban-0.9.dtd"
+    thubanids = [((dtd, n), (None, "id")) for n in
+                 ["fileshapesource", "filetable", "jointable",
+                  "derivedshapesource"]]
+    thubanidrefs = [((dtd, n), (None, m)) for n, m in
+                    [("layer", "shapestore"),
+                     ("jointable", "left"),
+                     ("jointable", "right"),
+                     ("derivedshapesource", "table"),
+                     ("derivedshapesource", "shapesource")]]
+    filenames = [((dtd, n), (None, m)) for n, m in
+                 [("fileshapesource", "filename"),
+                  ("rasterlayer", "filename"),
+                  ("filetable", "filename")]]
+    del n, m, dtd
+
+
+
+class ClassificationTest(LoadSessionTest):
+
+    """
+    Base class for tests that do some detailed checking of classifications
+    """
+
+    def TestLayers(self, layers, expected):
+        TITLE = 0
+        NUM_GROUPS = 1
+        CLASSES = 2
+        GROUP_TYPE = 0
+        GROUP_DATA = 1
+        GROUP_LABEL = 2
+        GROUP_PROPS = 3
+
+        eq = self.assertEquals
+
+        eq(len(layers), len(expected))
+
+        for layer, data in zip(layers, expected):
+            eq(layer.Title(), data[TITLE])
+
+            clazz = layer.GetClassification()
+            eq(clazz.GetNumGroups(), data[NUM_GROUPS])
+            eq(clazz.GetNumGroups() + 1, len(data[CLASSES]))
+
+            i = 0
+            for group in clazz:
+                props = ClassGroupProperties()
+                props.SetLineColor(
+                    parse_color(data[CLASSES][i][GROUP_PROPS][0]))
+                props.SetLineWidth(data[CLASSES][i][GROUP_PROPS][1])
+                props.SetFill(
+                    parse_color(data[CLASSES][i][GROUP_PROPS][2]))
+
+                if data[CLASSES][i][GROUP_TYPE] == "default":
+                    g = ClassGroupDefault(props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "range":
+                    g = ClassGroupRange((data[CLASSES][i][GROUP_DATA][0],
+                                         data[CLASSES][i][GROUP_DATA][1]),
+                                        props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "single":
+                    g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],
+                                          props, data[CLASSES][i][GROUP_LABEL])
+
+                eq(group, g)
+
+                i += 1
+
+
+
+class TestSingleLayer(LoadSessionTest):
+
+    # Note: The use of &amp; and non-ascii characters is deliberate. We
+    # want to test whether the loading code handles that correctly.
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.9.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd"
+        title="Stra\xc3\x9fen &amp; Landmarken">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="\xc3\x9cbersicht">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true"
+                stroke="#000000" title="K\xc3\xbcste" stroke_width="1"
+                fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session with a single map with a single layer"""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        # Check the title
+        eq(session.Title(), internal_from_unicode(u"Stra\xdfen & Landmarken"))
+
+        # the session has one map.
+        maps = session.Maps()
+        eq(len(maps), 1)
+
+        # Check the map's attributes
+        map = maps[0]
+        eq(map.Title(), internal_from_unicode(u"\xdcbersicht"))
+
+        # the map has a single layer
+        layers = map.Layers()
+        eq(len(layers), 1)
+
+        # Check the layer attributes
+        layer = layers[0]
+        eq(layer.Title(), internal_from_unicode(u"K\xfcste"))
+        self.failUnless(filenames_equal(layer.ShapeStore().FileName(),
+                                        os.path.join(self.temp_dir(),
+                                                     os.pardir, os.pardir,
+                                                     "Data", "iceland",
+                                                     "political.shp")))
+        eq(layer.GetClassification().GetDefaultFill(), Transparent)
+        eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")
+        eq(layer.Visible(), True)
+
+        self.session.Destroy()
+        self.session = None
+
+
+class TestLayerVisibility(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.9.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="false" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test that the visible flag is correctly loaded for a layer."""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+        maps = session.Maps()
+        eq(len(maps), 1)
+        map = maps[0]
+        layers = map.Layers()
+        eq(len(layers), 1)
+        layer = layers[0]
+
+        eq(layer.Visible(), False)
+
+
+class TestClassification(ClassificationTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban.dtd">
+<session title="single map&amp;layer">
+	<map title="Test Map">
+		<projection>
+			<parameter value="zone=26"/>
+			<parameter value="proj=utm"/>
+			<parameter value="ellps=clrk66"/>
+		</projection>
+		<layer title="My Layer" stroke_width="1" fill="None"
+                    filename="../../Data/iceland/political.shp"
+                    stroke="#000000">
+            <classification field="POPYREG" field_type="string">
+                <clnull>
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+                <clpoint value="1">
+                    <cldata stroke="#000000" stroke_width="10" fill="None"/>
+                </clpoint>
+                <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
+                         label="\xc3\x9cml\xc3\xa4uts">
+                    <cldata fill="None" stroke="#000000" stroke_width="1"/>
+                </clpoint>
+            </classification>
+        </layer>
+		<layer title="My Layer 2" stroke_width="1" fill="None"
+                    filename="../../Data/iceland/political.shp"
+                    stroke="#000000">
+            <classification field="AREA" field_type="double">
+                <clnull>
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clnull>
+                <clrange min="0" max="1">
+                    <cldata stroke="#111111" stroke_width="1" fill="None"/>
+                </clrange>
+                <clpoint value=".5">
+                    <cldata stroke="#000000" stroke_width="1" fill="#111111"/>
+                </clpoint>
+                <clrange min="-1" max="0">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clrange>
+                <clpoint value="-.5">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+	</map>
+</session>
+'''
+
+    def test(self):
+        """Load a Thuban session with a map and classified layers."""
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        expected = [("My Layer", 3,
+                        [("default", (), "",
+                            ("#000000", 1, "None")),
+                         ("single", "1", "",
+                            ("#000000", 2, "None")),
+                         ("single", "1", "",
+                            ("#000000", 10, "None")),
+                         ("single", internal_from_unicode(u"\xe4\xf6\xfc"),
+                          internal_from_unicode(u"\xdcml\xe4uts"),
+                            ("#000000", 1, "None"))]),
+                     ("My Layer 2", 4,
+                         [("default", (), "",
+                            ("#000000", 2, "None")),
+                          ("range", (0, 1), "",
+                            ("#111111", 1, "None")),
+                          ("single", .5, "",
+                            ("#000000", 1, "#111111")),
+                          ("range", (-1, 0), "",
+                            ("#000000", 1, "None")),
+                          ("single", -.5, "",
+                            ("#000000", 1, "None"))])]
+
+        self.TestLayers(map.Layers(), expected)
+
+
+class TestLabels(ClassificationTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.9.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None">
+            <classification field="POPYREG" field_type="string">
+                <clnull label="hallo">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint label="welt" value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session and test for reading the group labels."""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        expected = [("My Layer", 1,
+                        [("default", (), "hallo",
+                            ("#000000", 1, "None")),
+                         ("single", "1", "welt",
+                            ("#000000", 2, "None"))])]
+
+        self.TestLayers(map.Layers(), expected)
+
+
+class TestLayerProjection(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.9.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D2"
+        filename="../../Data/iceland/roads-line.shp"/>
+    <fileshapesource filetype="shapefile" id="D4"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D4" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None">
+            <projection name="hello">
+                <parameter value="zone=13"/>
+                <parameter value="proj=tmerc"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+            <classification field="POPYREG" field_type="string">
+                <clnull label="hallo">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint label="welt" value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+        <layer shapestore="D2" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None">
+            <projection name="Unknown">
+                <parameter value="proj=lcc"/>
+                <parameter value="lat_1=10"/>
+                <parameter value="lat_2=20"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test loading layers with projections"""
+        eq = self.assertEquals
+        neq = self.assertNotEqual
+
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        layers = map.Layers() # two layers in the sample
+
+        # test layer with a named projection
+        proj = layers[0].GetProjection()
+        neq(proj, None)
+        eq(proj.GetName(), "hello")
+        eq(proj.GetParameter("proj"), "tmerc")
+        eq(proj.GetParameter("zone"), "13")
+        eq(proj.GetParameter("ellps"), "clrk66")
+
+        # test layer with an unnamed projection
+        proj = layers[1].GetProjection()
+        neq(proj, None)
+        eq(proj.GetName(), "Unknown")
+        eq(proj.GetParameter("proj"), "lcc")
+        eq(proj.GetParameter("lat_1"), "10")
+        eq(proj.GetParameter("lat_2"), "20")
+        eq(proj.GetParameter("ellps"), "clrk66")
+
+
+
+class TestRasterLayer(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.9.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd"
+        title="single map&amp;layer">
+    <map title="Test Map">
+        <rasterlayer visible="false" filename="../../Data/iceland/island.tif"
+                title="My RasterLayer"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        eq = self.assertEquals
+        neq = self.assertNotEqual
+
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        layer = map.Layers()[0] # one layer in the sample
+
+        eq(layer.Title(), "My RasterLayer")
+        self.failIf(layer.Visible())
+        self.failUnless(filenames_equal(layer.GetImageFilename(),
+                                        os.path.join(self.temp_dir(),
+                                                     os.pardir, os.pardir,
+                                                     "Data", "iceland",
+                                                     "island.tif")))
+
+
+class TestJoinedTable(LoadSessionTest):
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.9.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd" title="A Joined Table session">
+    <fileshapesource filetype="shapefile" id="D137227612"
+        filename="../../Data/iceland/roads-line.shp"/>
+    <filetable filetype="DBF" filename="load_joinedtable.dbf" id="D136171140"
+        title="Some Title"/>
+    <jointable id="D136169900" title="Joined"
+        right="D136171140" left="D137227612"
+        leftcolumn="RDLNTYPE" rightcolumn="RDTYPE"
+        jointype="LEFT OUTER"/>
+    <derivedshapesource table="D136169900" shapesource="D137227612"
+        id="D136170932"/>
+    <map title="Test Map">
+        <layer shapestore="D136170932" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def setUp(self):
+        """Extend inherited method to create the dbffile for the join"""
+        LoadSessionTest.setUp(self)
+        dbffile = self.temp_file_name("load_joinedtable.dbf")
+        dbf = dbflib.create(dbffile)
+        dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
+        dbf.add_field("TEXT", dbflib.FTString, 10, 0)
+        dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
+        dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
+        dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
+        dbf.close()
+
+    def test(self):
+        """Test loading a session containing a joined table"""
+        session = load_session(self.filename())
+        self.session = session
+
+        tables = session.Tables()
+        self.assertEquals(len(tables), 3)
+        # FIXME: The tests shouldn't assume a certain order of the tables
+        self.assertEquals(tables[0].Title(), "Some Title")
+        self.assertEquals(tables[1].Title(), "Joined")
+        self.assertEquals(tables[1].JoinType(), "LEFT OUTER")
+
+
+
+class TestPostGISLayer(LoadSessionTest):
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.9.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd"
+        title="unnamed session">
+    <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
+        dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
+    <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
+    <map title="unnamed map">
+        <layer shapestore="D143149420" visible="true" stroke="#000000"
+                title="landmarks" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def setUp(self):
+        """Extend the inherited method to start the postgis server
+
+        Furthermore, patch the file contents with the real postgis db
+        information
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.postgisdb = self.server.get_default_static_data_db()
+
+        self.file_contents = self.__class__.file_contents % {
+            "dbname": self.postgisdb.dbname,
+            "user": self.server.user_name,
+            "port": self.server.port,
+            "host": self.server.host}
+        LoadSessionTest.setUp(self)
+
+    def test(self):
+        """Test loading a session containing a postgis shapestore"""
+        session = load_session(self.filename())
+        self.session = session
+        connections = session.DBConnections()
+        self.assertEquals(len(connections), 1)
+        conn = connections[0]
+        for attr, value in [("host", self.server.host),
+                            ("port", str(self.server.port)),
+                            ("user", self.server.user_name),
+                            ("dbname", self.postgisdb.dbname)]:
+            self.assertEquals(getattr(conn, attr), value)
+        layer = session.Maps()[0].Layers()[0]
+        self.failUnless(layer.ShapeStore().DBConnection() is conn)
+
+
+class TestPostGISLayerPassword(LoadSessionTest):
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.9.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd"
+        title="unnamed session">
+    <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
+        dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
+    <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
+    <map title="unnamed map">
+        <layer shapestore="D143149420" visible="true" stroke="#000000"
+                title="landmarks" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def setUp(self):
+        """Extend the inherited method to start the postgis server
+
+        Furthermore, patch the file contents with the real postgis db
+        information
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.postgisdb = self.server.get_default_static_data_db()
+
+        self.file_contents = self.__class__.file_contents % {
+            "dbname": self.postgisdb.dbname,
+            "user": self.server.user_name,
+            "port": self.server.port,
+            "host": self.server.host}
+        LoadSessionTest.setUp(self)
+
+        self.db_connection_callback_called = False
+        self.server.require_authentication(True)
+
+    def tearDown(self):
+        """Extend the inherited method to switch off postgresql authentication
+        """
+        self.server.require_authentication(False)
+        LoadSessionTest.tearDown(self)
+
+    def db_connection_callback(self, params, message):
+        """Implementation of Thuban.Model.hooks.query_db_connection_parameters
+        """
+        self.assertEquals(params,
+                          {"dbname": self.postgisdb.dbname,
+                           "user": self.server.user_name,
+                           "port": str(self.server.port),
+                           "host": self.server.host})
+        self.db_connection_callback_called = True
+        params = params.copy()
+        params["password"] = self.server.user_password
+        return params
+
+    def test_with_callback(self):
+        """Test loading a session with postgis, authentication and a callback
+        """
+        session = load_session(self.filename(),
+                      db_connection_callback = self.db_connection_callback)
+        self.session = session
+        connections = session.DBConnections()
+        self.assertEquals(len(connections), 1)
+        conn = connections[0]
+        for attr, value in [("host", self.server.host),
+                            ("port", str(self.server.port)),
+                            ("user", self.server.user_name),
+                            ("dbname", self.postgisdb.dbname)]:
+            self.assertEquals(getattr(conn, attr), value)
+        layer = session.Maps()[0].Layers()[0]
+        self.failUnless(layer.ShapeStore().DBConnection() is conn)
+        self.failUnless(self.db_connection_callback_called)
+
+    def test_without_callback(self):
+        """Test loading a session with postgis, authentication and no callback
+        """
+        # A password is required and there's no callback, so we should
+        # get a ConnectionError
+        self.assertRaises(ConnectionError, load_session, self.filename())
+
+    def test_cancel(self):
+        """Test loading a session with postgis and cancelling authentication
+        """
+        def cancel(*args):
+            self.db_connection_callback_called = True
+            return None
+
+        # If the user cancels, i.e. if the callbakc returns None, a
+        # LoadCancelled exception is raised.
+        self.assertRaises(LoadCancelled,
+                          load_session, self.filename(), cancel)
+        self.failUnless(self.db_connection_callback_called)
+
+
+class TestLoadError(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-0.9.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd"
+        title="single map&amp;layer">
+    <fileshapesource id="D1" filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true"
+                stroke="#000000" title="My Layer" stroke_width="1"
+                fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test loading a session missing a required attribute"""
+        # Don't use assertRaises to make sure that if a session is
+        # actually returned it gets destroyed properly.
+        try:
+            self.session = load_session(self.filename())
+        except LoadError, value:
+            # Check the actual messge in value to make sure the
+            # LoadError really was about the missing attribute
+            self.assertEquals(str(value),
+              "Element "
+              "(u'http://thuban.intevation.org/dtds/thuban-0.9.dtd',"
+              " u'fileshapesource') requires an attribute 'filetype'")
+        else:
+            self.fail("Missing filetype attribute doesn't raise LoadError")
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_load_1_0.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_load_1_0.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_load_1_0.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,884 @@
+# Copyright (c) 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test loading a thuban session from a file written by Thuban 1.0 or an 1.0aX
+
+See test_load.py for how the various test_load*.py files relate to each other.
+"""
+
+__version__ = "$Revision: 2642 $"
+# $Source$
+# $Id: test_load_1_0.py 2642 2005-07-01 20:49:04Z bh $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+import postgissupport
+from xmlsupport import sax_eventlist
+
+import dbflib
+import shapelib
+
+from Thuban import internal_from_unicode
+from Thuban.Model.save import save_session
+from Thuban.Model.load import load_session, parse_color, LoadError, \
+     LoadCancelled
+from Thuban.Model.color import Transparent
+from Thuban.Model.classification import ClassGroupProperties, ClassGroupRange,\
+    ClassGroupSingleton, ClassGroupDefault
+from Thuban.Model.postgisdb import ConnectionError
+from Thuban.Model.table import DBFTable, MemoryTable, \
+     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING, \
+     table_to_dbf
+from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
+     ALIGN_LEFT, ALIGN_RIGHT, ALIGN_BASELINE
+
+
+def filenames_equal(name1, name2):
+    """Return true if the filenames name1 and name2 are equal.
+
+    On systems where it is available, simply use os.path.samefile,
+    otherwise return whether the normalized versions of the filenames
+    according to os.path.normpath are equal.
+    """
+    if hasattr(os.path, "samefile"):
+        return os.path.samefile(name1, name2)
+    return os.path.normpath(name1) == os.path.normpath(name2)
+
+
+
+class LoadSessionTest(support.FileLoadTestCase):
+
+    """Base class for .thuban file loading tests
+
+    Basically the same as the FileLoadTestCase, except that all tests
+    use the '.thuban' extension by default and that setUp and tearDown
+    handle sessions.
+    """
+
+    file_extension = ".thuban"
+
+    def setUp(self):
+        """Create the test files"""
+        support.FileLoadTestCase.setUp(self)
+        self.session = None
+
+    def tearDown(self):
+        if self.session is not None:
+            self.session.Destroy()
+        self.session = None
+
+
+    dtd = "http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+    thubanids = [((dtd, n), (None, "id")) for n in
+                 ["fileshapesource", "filetable", "jointable",
+                  "derivedshapesource"]]
+    thubanidrefs = [((dtd, n), (None, m)) for n, m in
+                    [("layer", "shapestore"),
+                     ("jointable", "left"),
+                     ("jointable", "right"),
+                     ("derivedshapesource", "table"),
+                     ("derivedshapesource", "shapesource")]]
+
+    # The filenames in the tests should be understandable on all
+    # currently supported platforms so filenames is an empty list
+    filenames = []
+
+    del n, m, dtd
+
+
+
+class ClassificationTest(LoadSessionTest):
+
+    """
+    Base class for tests that do some detailed checking of classifications
+    """
+
+    def TestLayers(self, layers, expected):
+        TITLE = 0
+        NUM_GROUPS = 1
+        CLASSES = 2
+        GROUP_TYPE = 0
+        GROUP_DATA = 1
+        GROUP_LABEL = 2
+        GROUP_PROPS = 3
+
+        eq = self.assertEquals
+
+        eq(len(layers), len(expected))
+
+        for layer, data in zip(layers, expected):
+            eq(layer.Title(), data[TITLE])
+
+            clazz = layer.GetClassification()
+            eq(clazz.GetNumGroups(), data[NUM_GROUPS])
+            eq(clazz.GetNumGroups() + 1, len(data[CLASSES]))
+
+            i = 0
+            for group in clazz:
+                props = ClassGroupProperties()
+                props.SetLineColor(
+                    parse_color(data[CLASSES][i][GROUP_PROPS][0]))
+                props.SetLineWidth(data[CLASSES][i][GROUP_PROPS][1])
+                props.SetFill(
+                    parse_color(data[CLASSES][i][GROUP_PROPS][2]))
+
+                if data[CLASSES][i][GROUP_TYPE] == "default":
+                    g = ClassGroupDefault(props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "range":
+                    g = ClassGroupRange((data[CLASSES][i][GROUP_DATA][0],
+                                         data[CLASSES][i][GROUP_DATA][1]),
+                                        props, data[CLASSES][i][GROUP_LABEL])
+                elif data[CLASSES][i][GROUP_TYPE] == "single":
+                    g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],
+                                          props, data[CLASSES][i][GROUP_LABEL])
+
+                eq(group, g)
+
+                i += 1
+
+
+
+class TestSingleLayer(LoadSessionTest):
+
+    # Note: The use of &amp; and non-ascii characters is deliberate. We
+    # want to test whether the loading code handles that correctly.
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+        title="Stra\xc3\x9fen &amp; Landmarken">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="\xc3\x9cbersicht">
+        <projection epsg="32627" name="WGS 84 / UTM zone 27N">
+            <parameter value="datum=WGS84"/>
+            <parameter value="ellps=WGS84"/>
+            <parameter value="proj=utm"/>
+            <parameter value="units=m"/>
+            <parameter value="zone=27"/>
+        </projection>
+        <layer shapestore="D1" visible="true"
+                stroke="#000000" title="K\xc3\xbcste" stroke_width="1"
+                fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session with a single map with a single layer"""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        # Check the title
+        eq(session.Title(), internal_from_unicode(u"Stra\xdfen & Landmarken"))
+
+        # the session has one map.
+        maps = session.Maps()
+        eq(len(maps), 1)
+
+        # Check the map's attributes
+        map = maps[0]
+        eq(map.Title(), internal_from_unicode(u"\xdcbersicht"))
+        proj = map.GetProjection()
+        eq(proj.GetName(), "WGS 84 / UTM zone 27N")
+        eq(proj.EPSGCode(), "32627")
+        params = proj.GetAllParameters()
+        params.sort()
+        eq(params, ["datum=WGS84", "ellps=WGS84", "proj=utm", "units=m",
+                    "zone=27"])
+
+        # the map has a single layer
+        layers = map.Layers()
+        eq(len(layers), 1)
+
+        # Check the layer attributes
+        layer = layers[0]
+        eq(layer.Title(), internal_from_unicode(u"K\xfcste"))
+        self.failUnless(filenames_equal(layer.ShapeStore().FileName(),
+                                        os.path.join(self.temp_dir(),
+                                                     os.pardir, os.pardir,
+                                                     "Data", "iceland",
+                                                     "political.shp")))
+        eq(layer.GetClassification().GetDefaultFill(), Transparent)
+        eq(layer.GetClassification().GetDefaultLineColor().hex(), "#000000")
+        eq(layer.Visible(), True)
+
+        self.session.Destroy()
+        self.session = None
+
+    def test_leak(self):
+        """Test load_session for resource leaks
+
+        The load_session function had a resource leak in that it created
+        cyclic references. The objects would have been eventually
+        collected by the garbage collector but too late. One symptom is
+        that when layers are removed so that the last normal reference
+        owned indirectly by the session to a shape store goes away, the
+        shape store is not actually removed from the session even though
+        the session only keeps weak references because there are still
+        references owned by the cyclic garbage.
+        """
+        session = load_session(self.filename())
+        self.session = session
+
+        # sanity check
+        self.assertEquals(len(session.ShapeStores()), 1)
+
+        # remove the map. The shapestore should go away too
+        session.RemoveMap(session.Maps()[0])
+        self.assertEquals(len(session.ShapeStores()), 0)
+
+
+class TestNonAsciiColumnName(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+        title="Non ASCII column name test">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="TestNonAsciiColumnName.shp"/>
+    <map title="map">
+        <projection name="Some Projection">
+            <parameter value="datum=WGS84"/>
+            <parameter value="ellps=WGS84"/>
+            <parameter value="proj=utm"/>
+            <parameter value="units=m"/>
+            <parameter value="zone=27"/>
+        </projection>
+        <layer shapestore="D1" visible="true"
+                stroke="#000000" title="layer" stroke_width="1"
+                fill="None">
+            <classification field="Fl\xc3\xa4che" field_type="double">
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session with a single map with a single layer"""
+
+        # Create a shapefile and a dbffile with a non-ascii column name
+        dbffile = self.temp_file_name("TestNonAsciiColumnName.dbf")
+        shpfile = self.temp_file_name("TestNonAsciiColumnName.shp")
+        dbf = dbflib.create(dbffile)
+        dbf.add_field('Fl\xe4che', dbflib.FTDouble, 10, 5)
+        dbf.write_record(0, (0.0,))
+        dbf.close()
+        shp = shapelib.create(shpfile, shapelib.SHPT_POLYGON)
+        shp.write_object(-1, shapelib.SHPObject(shapelib.SHPT_POLYGON, 1,
+                                                [[(0,0), (10, 10), (10, 0),
+                                                  (0, 0)]]))
+        shp.close()
+
+        try:
+            session = load_session(self.filename())
+        except ValueError, v:
+            # Usually if the field name is not decoded properly the
+            # loading fails because the field type mentioned in the file
+            # is not None as returned from the layer for a non-existing
+            # column name so we check for that and report it as failure.
+            # Other exceptions are errors in the test case.
+            if str(v) == "xml field type differs from database!":
+                self.fail("Cannot load file with non-ascii column names")
+            else:
+                raise
+        self.session = session
+
+        # In case Thuban could load the file anyway (i.e. no ValueError
+        # exception in load_session()), check explicitly whether the
+        # field name was decoded properly. The test will probably lead
+        # to a UnicodeError instead of a test failure so we check that
+        # too
+        layer = session.Maps()[0].Layers()[0]
+        try:
+            self.assertEquals(layer.GetClassificationColumn(), 'Fl\xe4che')
+        except UnicodeError:
+            # FIXME: Obviously this will have to change if Thuban ever
+            # supports unicode properly.
+            self.fail("Column name was not converted to a bytestring")
+
+
+class TestLayerVisibility(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="false" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test that the visible flag is correctly loaded for a layer."""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+        maps = session.Maps()
+        eq(len(maps), 1)
+        map = maps[0]
+        layers = map.Layers()
+        eq(len(layers), 1)
+        layer = layers[0]
+
+        eq(layer.Visible(), False)
+
+
+class TestClassification(ClassificationTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D138389860"
+        filename="../../Data/iceland/political.shp"/>
+    <fileshapesource filetype="shapefile" id="D138504492"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D138389860" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None">
+            <classification field="POPYREG" field_type="string">
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint label="" value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+                <clpoint label="" value="1">
+                    <cldata stroke="#000000" stroke_width="10" fill="None"/>
+                </clpoint>
+                <clpoint label="\xc3\x9cml\xc3\xa4uts"
+                        value="\xc3\xa4\xc3\xb6\xc3\xbc">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+        <layer shapestore="D138504492" visible="true" stroke="#000000"
+                title="My Layer 2" stroke_width="2" fill="None">
+            <classification field="AREA" field_type="double">
+                <clnull label="">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clnull>
+                <clrange label="" range="[0;1[">
+                    <cldata stroke="#111111" stroke_width="1" fill="None"/>
+                </clrange>
+                <clpoint label="" value="0.5">
+                    <cldata stroke="#000000" stroke_width="1" fill="#111111"/>
+                </clpoint>
+                <clrange label="" range="[-1;0[">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clrange>
+                <clpoint label="" value="-0.5">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a Thuban session with a map and classified layers."""
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        expected = [("My Layer", 3,
+                        [("default", (), "",
+                            ("#000000", 1, "None")),
+                         ("single", "1", "",
+                            ("#000000", 2, "None")),
+                         ("single", "1", "",
+                            ("#000000", 10, "None")),
+                         ("single", internal_from_unicode(u"\xe4\xf6\xfc"),
+                          internal_from_unicode(u"\xdcml\xe4uts"),
+                            ("#000000", 1, "None"))]),
+                     ("My Layer 2", 4,
+                         [("default", (), "",
+                            ("#000000", 2, "None")),
+                          ("range", (0, 1), "",
+                            ("#111111", 1, "None")),
+                          ("single", .5, "",
+                            ("#000000", 1, "#111111")),
+                          ("range", (-1, 0), "",
+                            ("#000000", 1, "None")),
+                          ("single", -.5, "",
+                            ("#000000", 1, "None"))])]
+
+        self.TestLayers(map.Layers(), expected)
+
+
+class TestLabels(ClassificationTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D1"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None">
+            <classification field="POPYREG" field_type="string">
+                <clnull label="hallo">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint label="welt" value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Load a session and test for reading the group labels."""
+        eq = self.assertEquals
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        expected = [("My Layer", 1,
+                        [("default", (), "hallo",
+                            ("#000000", 1, "None")),
+                         ("single", "1", "welt",
+                            ("#000000", 2, "None"))])]
+
+        self.TestLayers(map.Layers(), expected)
+
+class TestLayerProjection(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+        title="single map&amp;layer">
+    <fileshapesource filetype="shapefile" id="D2"
+        filename="../../Data/iceland/roads-line.shp"/>
+    <fileshapesource filetype="shapefile" id="D4"
+        filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D4" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None">
+            <projection name="hello">
+                <parameter value="zone=13"/>
+                <parameter value="proj=tmerc"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+            <classification field="POPYREG" field_type="string">
+                <clnull label="hallo">
+                    <cldata stroke="#000000" stroke_width="1" fill="None"/>
+                </clnull>
+                <clpoint label="welt" value="1">
+                    <cldata stroke="#000000" stroke_width="2" fill="None"/>
+                </clpoint>
+            </classification>
+        </layer>
+        <layer shapestore="D2" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None">
+            <projection name="Unknown">
+                <parameter value="proj=lcc"/>
+                <parameter value="lat_1=10"/>
+                <parameter value="lat_2=20"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+        </layer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test loading layers with projections"""
+        eq = self.assertEquals
+        neq = self.assertNotEqual
+
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        layers = map.Layers() # two layers in the sample
+
+        # test layer with a named projection
+        proj = layers[0].GetProjection()
+        neq(proj, None)
+        eq(proj.GetName(), "hello")
+        eq(proj.GetParameter("proj"), "tmerc")
+        eq(proj.GetParameter("zone"), "13")
+        eq(proj.GetParameter("ellps"), "clrk66")
+
+        # test layer with an unnamed projection
+        proj = layers[1].GetProjection()
+        neq(proj, None)
+        eq(proj.GetName(), "Unknown")
+        eq(proj.GetParameter("proj"), "lcc")
+        eq(proj.GetParameter("lat_1"), "10")
+        eq(proj.GetParameter("lat_2"), "20")
+        eq(proj.GetParameter("ellps"), "clrk66")
+
+
+class TestRasterLayer(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+        title="single map&amp;layer">
+    <map title="Test Map">
+        <rasterlayer visible="false" filename="../../Data/iceland/island.tif"
+                title="My RasterLayer"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        eq = self.assertEquals
+        neq = self.assertNotEqual
+
+        session = load_session(self.filename())
+        self.session = session
+
+        map = self.session.Maps()[0] # only one map in the sample
+
+        layer = map.Layers()[0] # one layer in the sample
+
+        eq(layer.Title(), "My RasterLayer")
+        self.failIf(layer.Visible())
+        self.failUnless(filenames_equal(layer.GetImageFilename(),
+                                        os.path.join(self.temp_dir(),
+                                                     os.pardir, os.pardir,
+                                                     "Data", "iceland",
+                                                     "island.tif")))
+
+class TestJoinedTable(LoadSessionTest):
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd" title="A Joined Table session">
+    <fileshapesource filetype="shapefile" id="D137227612"
+        filename="../../Data/iceland/roads-line.shp"/>
+    <filetable filetype="DBF" filename="load_joinedtable.dbf" id="D136171140"
+        title="Some Title"/>
+    <jointable id="D136169900" title="Joined"
+        right="D136171140" left="D137227612"
+        leftcolumn="RDLNTYPE" rightcolumn="RDTYPE"
+        jointype="LEFT OUTER"/>
+    <derivedshapesource table="D136169900" shapesource="D137227612"
+        id="D136170932"/>
+    <map title="Test Map">
+        <layer shapestore="D136170932" visible="true" stroke="#000000"
+                title="My Layer" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def setUp(self):
+        """Extend inherited method to create the dbffile for the join"""
+        LoadSessionTest.setUp(self)
+        dbffile = self.temp_file_name("load_joinedtable.dbf")
+        dbf = dbflib.create(dbffile)
+        dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
+        dbf.add_field("TEXT", dbflib.FTString, 10, 0)
+        dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
+        dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
+        dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
+        dbf.close()
+
+    def test(self):
+        """Test loading a session containing a joined table"""
+        session = load_session(self.filename())
+        self.session = session
+
+        tables = session.Tables()
+        self.assertEquals(len(tables), 3)
+        # FIXME: The tests shouldn't assume a certain order of the tables
+        self.assertEquals(tables[0].Title(), "Some Title")
+        self.assertEquals(tables[1].Title(), "Joined")
+        self.assertEquals(tables[1].JoinType(), "LEFT OUTER")
+
+class TestLabelLayer(LoadSessionTest):
+
+    # Note that the labels deliberately contain non-ascii characters to
+    # test whether they're supported correctly.
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd" title="Thuban sample session">
+    <fileshapesource filetype="shapefile" id="D145265052"
+        filename="../../Data/iceland/political.shp"/>
+    <fileshapesource filetype="shapefile" id="D145412868"
+        filename="../../Data/iceland/cultural_landmark-point.shp"/>
+    <map title="Iceland map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D145265052" visible="true" stroke="#000000"
+                title="political" stroke_width="1" fill="#c0c0c0">
+            <projection name="Geographic">
+                <parameter value="proj=latlong"/>
+                <parameter value="to_meter=0.017453"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+        </layer>
+        <layer shapestore="D145412868" visible="true" stroke="#000000"
+                title="landmarks" stroke_width="1" fill="#ffff00">
+            <projection name="Geographic">
+                <parameter value="proj=latlong"/>
+                <parameter value="to_meter=0.017453"/>
+                <parameter value="ellps=clrk66"/>
+            </projection>
+        </layer>
+        <labellayer>
+            <label x="-21.5" y="64.25" text="RUINS"
+                halign="left" valign="center"/>
+            <label x="-15.125" y="64.75" text="H\xc3\xbctte"
+                halign="right" valign="top"/>
+        </labellayer>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test loading a session with a label layer"""
+        session = load_session(self.filename())
+        self.session = session
+
+        label_layer = self.session.Maps()[0].LabelLayer()
+        expected_labels = [(-21.5, 64.25, "RUINS", ALIGN_LEFT, ALIGN_CENTER),
+                           (-15.125, 64.75, internal_from_unicode(u"H\xfctte"),
+                            ALIGN_RIGHT, ALIGN_TOP),
+                           ]
+        for label, values in zip(label_layer.Labels(), expected_labels):
+            self.assertEquals((label.x, label.y, label.text, label.halign,
+                               label.valign),
+                              values)
+
+class TestPostGISLayer(LoadSessionTest):
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+        title="unnamed session">
+    <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
+        dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
+    <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
+    <map title="unnamed map">
+        <layer shapestore="D143149420" visible="true" stroke="#000000"
+                title="landmarks" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def setUp(self):
+        """Extend the inherited method to start the postgis server
+
+        Furthermore, patch the file contents with the real postgis db
+        information
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.postgisdb = self.server.get_default_static_data_db()
+
+        self.file_contents = self.__class__.file_contents % {
+            "dbname": self.postgisdb.dbname,
+            "user": self.server.user_name,
+            "port": self.server.port,
+            "host": self.server.host}
+        LoadSessionTest.setUp(self)
+
+    def test(self):
+        """Test loading a session containing a postgis shapestore"""
+        session = load_session(self.filename())
+        self.session = session
+        connections = session.DBConnections()
+        self.assertEquals(len(connections), 1)
+        conn = connections[0]
+        for attr, value in [("host", self.server.host),
+                            ("port", str(self.server.port)),
+                            ("user", self.server.user_name),
+                            ("dbname", self.postgisdb.dbname)]:
+            self.assertEquals(getattr(conn, attr), value)
+        layer = session.Maps()[0].Layers()[0]
+        self.failUnless(layer.ShapeStore().DBConnection() is conn)
+
+
+class TestPostGISLayerPassword(LoadSessionTest):
+
+    file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+        title="unnamed session">
+    <dbconnection port="%(port)s" host="%(host)s" user="%(user)s"
+        dbtype="postgis" id="D142684948" dbname="%(dbname)s"/>
+    <dbshapesource tablename="landmarks" id="D143149420" dbconn="D142684948"/>
+    <map title="unnamed map">
+        <layer shapestore="D143149420" visible="true" stroke="#000000"
+                title="landmarks" stroke_width="1" fill="None"/>
+    </map>
+</session>
+'''
+
+    def setUp(self):
+        """Extend the inherited method to start the postgis server
+
+        Furthermore, patch the file contents with the real postgis db
+        information
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.postgisdb = self.server.get_default_static_data_db()
+
+        self.file_contents = self.__class__.file_contents % {
+            "dbname": self.postgisdb.dbname,
+            "user": self.server.user_name,
+            "port": self.server.port,
+            "host": self.server.host}
+        LoadSessionTest.setUp(self)
+
+        self.db_connection_callback_called = False
+        self.server.require_authentication(True)
+
+    def tearDown(self):
+        """Extend the inherited method to switch off postgresql authentication
+        """
+        self.server.require_authentication(False)
+        LoadSessionTest.tearDown(self)
+
+    def db_connection_callback(self, params, message):
+        """Implementation of Thuban.Model.hooks.query_db_connection_parameters
+        """
+        self.assertEquals(params,
+                          {"dbname": self.postgisdb.dbname,
+                           "user": self.server.user_name,
+                           "port": str(self.server.port),
+                           "host": self.server.host})
+        self.db_connection_callback_called = True
+        params = params.copy()
+        params["password"] = self.server.user_password
+        return params
+
+    def test_with_callback(self):
+        """Test loading a session with postgis, authentication and a callback
+        """
+        session = load_session(self.filename(),
+                      db_connection_callback = self.db_connection_callback)
+        self.session = session
+        connections = session.DBConnections()
+        self.assertEquals(len(connections), 1)
+        conn = connections[0]
+        for attr, value in [("host", self.server.host),
+                            ("port", str(self.server.port)),
+                            ("user", self.server.user_name),
+                            ("dbname", self.postgisdb.dbname)]:
+            self.assertEquals(getattr(conn, attr), value)
+        layer = session.Maps()[0].Layers()[0]
+        self.failUnless(layer.ShapeStore().DBConnection() is conn)
+        self.failUnless(self.db_connection_callback_called)
+
+    def test_without_callback(self):
+        """Test loading a session with postgis, authentication and no callback
+        """
+        # A password is required and there's no callback, so we should
+        # get a ConnectionError
+        self.assertRaises(ConnectionError, load_session, self.filename())
+
+    def test_cancel(self):
+        """Test loading a session with postgis and cancelling authentication
+        """
+        def cancel(*args):
+            self.db_connection_callback_called = True
+            return None
+
+        # If the user cancels, i.e. if the callbakc returns None, a
+        # LoadCancelled exception is raised.
+        self.assertRaises(LoadCancelled,
+                          load_session, self.filename(), cancel)
+        self.failUnless(self.db_connection_callback_called)
+
+
+class TestLoadError(LoadSessionTest):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE session SYSTEM "thuban-1.0.dtd">
+<session xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd"
+        title="single map&amp;layer">
+    <fileshapesource id="D1" filename="../../Data/iceland/political.shp"/>
+    <map title="Test Map">
+        <projection name="Unknown">
+            <parameter value="zone=26"/>
+            <parameter value="proj=utm"/>
+            <parameter value="ellps=clrk66"/>
+        </projection>
+        <layer shapestore="D1" visible="true"
+                stroke="#000000" title="My Layer" stroke_width="1"
+                fill="None"/>
+    </map>
+</session>
+'''
+
+    def test(self):
+        """Test loading a session missing a required attribute"""
+        # Don't use assertRaises to make sure that if a session is
+        # actually returned it gets destroyed properly.
+        try:
+            self.session = load_session(self.filename())
+        except LoadError, value:
+            # Check the actual messge in value to make sure the
+            # LoadError really was about the missing attribute
+            self.assertEquals(str(value),
+              "Element "
+              "(u'http://thuban.intevation.org/dtds/thuban-1.0.0.dtd',"
+              " u'fileshapesource') requires an attribute 'filetype'")
+        else:
+            self.fail("Missing filetype attribute doesn't raise LoadError")
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_map.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_map.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_map.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,308 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Map class
+"""
+
+__version__ = "$Revision: 2575 $"
+# $Source$
+# $Id: test_map.py 2575 2005-02-22 11:09:32Z jan $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.messages import CHANGED, MAP_PROJECTION_CHANGED, \
+     MAP_LAYERS_CHANGED, MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED,\
+     MAP_STACKING_CHANGED, LAYER_VISIBILITY_CHANGED, LAYER_LEGEND_CHANGED, \
+     LAYER_CHANGED
+
+from Thuban.Model.session import Session
+from Thuban.Model.map import Map
+from Thuban.Model.layer import Layer
+from Thuban.Model.proj import Projection
+from Thuban.Model.color import Color
+
+
+class TestMapSimple(unittest.TestCase):
+
+    """Very simple test cases for Map"""
+
+    def test_initial_state(self):
+        """Test Map's initial state"""
+        map = Map("Test Map")
+        self.assertEquals(map.Title(), "Test Map")
+        self.assertEquals(map.Layers(), [])
+        label_layer = map.LabelLayer()
+        self.assertEquals(label_layer.Title(), "Labels")
+        self.assertEquals(label_layer.Labels(), [])
+        self.failIf(map.WasModified())
+        map.Destroy()
+
+    def test_empty_map(self):
+        """Test empty Map"""
+        map = Map("Test Map")
+        self.assertEquals(map.BoundingBox(), None)
+        self.assertEquals(map.ProjectedBoundingBox(), None)
+        self.failIf(map.HasLayers())
+        map.Destroy()
+
+
+class TestMapBase(unittest.TestCase, support.SubscriberMixin):
+
+    """Base class for Map test cases that test messages"""
+
+    def setUp(self):
+        """
+        Clear the message list, create self.map and subscribe to its messages
+        """
+        self.clear_messages()
+
+        # Create a Map and subscribe to all interesting channels.
+        self.map = Map("Test Map")
+        for channel in (CHANGED, 
+                        MAP_PROJECTION_CHANGED, 
+                        MAP_LAYERS_CHANGED,
+                        MAP_LAYERS_ADDED,
+                        MAP_LAYERS_REMOVED,
+                        MAP_STACKING_CHANGED,
+                        LAYER_VISIBILITY_CHANGED, 
+                        LAYER_LEGEND_CHANGED,
+                        LAYER_CHANGED):
+            self.map.Subscribe(channel, self.subscribe_with_params, channel)
+
+    def tearDown(self):
+        """Destroy self.map and self.session and clear the message list"""
+        if hasattr(self, "session"):
+            self.session.Destroy()
+            self.session = None
+        self.map.Destroy()
+        self.map = None
+        self.clear_messages()
+
+
+class TestMapAddLayer(TestMapBase):
+
+    """Simple test cases involving messages"""
+
+    def test_add_layer(self):
+        """Test Map.AddLayer"""
+        # make sure the created Map is unmodified
+        session = self.session = Session("Test session for %s" %self.__class__)
+        self.failIf(self.map.WasModified())
+        self.failIf(self.map.HasLayers())
+
+        # add a layer and check the result
+        filename = os.path.join("..", "Data", "iceland", "roads-line.shp")
+        roads = Layer("Roads", session.OpenShapefile(filename))
+        self.map.AddLayer(roads)
+        self.assertEquals(self.map.Layers(), [roads])
+        self.check_messages([(self.map, MAP_LAYERS_CHANGED),
+                             (self.map, MAP_LAYERS_ADDED)])
+        self.assert_(self.map.WasModified())
+        self.assert_(self.map.HasLayers())
+
+
+class TestMapWithContents(TestMapBase, support.FloatComparisonMixin):
+
+    """More complex Map test cases with messages that.
+
+    All test cases here start with a non-empty map.
+    """
+
+    def setUp(self):
+        """Extend the inherited method to also fill the Map.
+
+        Put some layers into the map created by the inherited method and
+        reset its modified flag. Make also sure that the list of
+        received messages is empty.
+        """
+        TestMapBase.setUp(self)
+        self.session = Session("Test session for %s" % self.__class__)
+        open_shp = self.session.OpenShapefile
+        self.arc_layer = Layer("Roads",
+                               open_shp(os.path.join("..", "Data", "iceland",
+                                                     "roads-line.shp")))
+        self.poly_layer = Layer("Political",
+                                open_shp(os.path.join("..", "Data", "iceland",
+                                                      "political.shp")))
+        self.map.AddLayer(self.arc_layer)
+        self.map.AddLayer(self.poly_layer)
+        self.map.UnsetModified()
+        self.clear_messages()
+
+    def tearDown(self):
+        TestMapBase.tearDown(self)
+        self.session = None
+        self.map = None
+        self.poly_layer = self.arc_layer = None
+
+    def test_remove_layer(self):
+        """Test Map.RemoveLayer"""
+        self.map.RemoveLayer(self.arc_layer)
+        self.assert_(self.map.WasModified())
+        self.assertEquals(self.map.Layers(), [self.poly_layer])
+        self.map.UnsetModified()
+        self.check_messages([(self.map, MAP_LAYERS_CHANGED),
+                             (self.map, MAP_LAYERS_REMOVED),
+                             (CHANGED,)])
+
+    def test_clear_layers(self):
+        """Test Map.ClearLayers"""
+        self.map.ClearLayers()
+        self.assertEquals(self.map.Layers(), [])
+        self.assertEquals(self.map.LabelLayer().Labels(), [])
+        self.check_messages([(MAP_LAYERS_CHANGED,),
+                             (self.map, MAP_LAYERS_CHANGED),
+                             (self.map, MAP_LAYERS_REMOVED)])
+        self.assert_(self.map.WasModified())
+        self.failIf(self.map.HasLayers())
+
+    def test_raise_layer(self):
+        """Test Map.RaiseLayer"""
+        self.map.RaiseLayer(self.arc_layer)
+        self.assertEquals(self.map.Layers(), [self.poly_layer, self.arc_layer])
+        self.check_messages([(self.map, MAP_LAYERS_CHANGED),
+                             (self.map, MAP_STACKING_CHANGED)])
+        self.assert_(self.map.WasModified())
+
+    def test_raise_layer_top(self):
+        """Test Map.MoveLayerToTop"""
+        open_shp = self.session.OpenShapefile
+        dummy = Layer("Roads",
+                      open_shp(os.path.join("..", "Data", "iceland",
+                                            "roads-line.shp")))
+        self.map.AddLayer(dummy)
+        self.clear_messages()
+
+        self.map.MoveLayerToTop(self.poly_layer)
+        self.assertEquals(self.map.Layers(), 
+                          [self.arc_layer, dummy, self.poly_layer])
+        self.check_messages([(self.map, MAP_LAYERS_CHANGED),
+                             (self.map, MAP_STACKING_CHANGED)])
+        self.assert_(self.map.WasModified())
+
+        self.map.RemoveLayer(dummy)
+
+    def test_lower_layer_bottom(self):
+        """Test Map.MoveLayerToBottom"""
+        open_shp = self.session.OpenShapefile
+        dummy = Layer("Roads",
+                      open_shp(os.path.join("..", "Data", "iceland",
+                                            "roads-line.shp")))
+        self.map.AddLayer(dummy)
+        self.clear_messages()
+
+        self.map.MoveLayerToBottom(dummy)
+        self.assertEquals(self.map.Layers(), 
+                          [dummy, self.arc_layer, self.poly_layer])
+        self.check_messages([(self.map, MAP_LAYERS_CHANGED),
+                             (self.map, MAP_STACKING_CHANGED)])
+        self.assert_(self.map.WasModified())
+
+        self.map.RemoveLayer(dummy)
+
+    def test_raise_highest_layer(self):
+        """Test Map.RaiseLayer with highest layer
+
+        Attempting to raise the highest layer should not modify the map.
+        In particular it should not send any messages.
+        """
+        self.map.RaiseLayer(self.poly_layer)
+        self.assertEquals(self.map.Layers(), [self.arc_layer, self.poly_layer])
+        self.check_messages([])
+        self.failIf(self.map.WasModified())
+
+    def test_lower_layer(self):
+        """Test Map.LowerLayer"""
+        self.map.LowerLayer(self.poly_layer)
+        self.assertEquals(self.map.Layers(), [self.poly_layer, self.arc_layer])
+        self.check_messages([(self.map, MAP_LAYERS_CHANGED),
+                             (self.map, MAP_STACKING_CHANGED)])
+        self.assert_(self.map.WasModified())
+
+    def test_lower_lowest_layer(self):
+        """Test Map.LowerLayer with lowest layer.
+
+        Attempting to lower the lowest layer should not modify the map.
+        In particular it should not send any messages.
+        """
+        self.map.LowerLayer(self.arc_layer)
+        self.assertEquals(self.map.Layers(), [self.arc_layer, self.poly_layer])
+        self.check_messages([])
+        self.failIf(self.map.WasModified())
+
+    def test_bounding_box(self):
+        """Test Map.BoundingBox"""
+        self.assertFloatSeqEqual(self.map.BoundingBox(),
+                                 (-24.546524047851562, 63.286754608154297,
+                                  -13.495815277099609, 66.563774108886719))
+
+    def test_projected_bounding_box(self):
+        """Test Map.ProjectedBoundingBox"""
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
+        self.map.SetProjection(proj)
+        self.assertFloatSeqEqual(self.map.ProjectedBoundingBox(),
+                                 (608873.03380603762, 7019694.6517963577,
+                                  1173560.0288053728, 7447353.2203218574),
+                                 epsilon = 1e-5)
+
+    def test_set_projection(self):
+        """Test Map.SetProjection"""
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
+        self.map.SetProjection(proj)
+        self.check_messages([(self.map, None, MAP_PROJECTION_CHANGED)])
+        self.assert_(self.map.WasModified())
+
+    def test_tree_info(self):
+        """Test Map.TreeInfo"""
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
+        self.map.SetProjection(proj)
+        # compute the extent string because there are platform
+        # differences in the way %g is handled:
+        # glibc: "%g" % 7.01969e+06 == "7.01969e+06"
+        # w32/VC: "%g" % 7.01969e+06 == "7.01969e+006"
+        extent = 'Extent (projected): (%g, %g, %g, %g)'\
+                 % (608873, 7.01969e+06, 1.17356e+06, 7.44735e+06)
+        self.assertEquals(self.map.TreeInfo(),
+                          ('Map: Test Map',
+                           [('Extent (lat-lon):'
+                             ' (-24.5465, 63.2868, -13.4958, 66.5638)'),
+                            extent,
+                            ('Projection',
+                             ['zone=26', 'proj=utm', 'ellps=clrk66']),
+                            self.poly_layer,
+                            self.arc_layer,
+                            self.map.LabelLayer()]))
+
+    def test_forwarding_visibility(self):
+        """Test Map's forwarding of Layer.SetVisible messages"""
+        self.poly_layer.SetVisible(0)
+        self.check_messages([(self.poly_layer, LAYER_VISIBILITY_CHANGED)])
+
+    def test_unset_modified(self):
+        """Test Map.UnsetModified.
+
+        Test whether a change to a layer results in the map being
+        considered modified and test whether then calling the map's
+        UnsetModified clears the changed flag in the layer as well.
+        """
+        self.failIf(self.map.WasModified())
+        self.poly_layer.GetClassification().SetDefaultFill(Color(0.0, 0.5, 1.0))
+        self.assert_(self.map.WasModified())
+        self.map.UnsetModified()
+        self.failIf(self.map.WasModified())
+        self.failIf(self.poly_layer.WasModified())
+        self.check_messages([(self.poly_layer, LAYER_CHANGED),
+                             (CHANGED,)])
+
+if __name__ == "__main__":
+    support.run_tests()
+

Added: packages/thuban/branches/upstream/current/test/test_memory_table.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_memory_table.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_memory_table.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,147 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the MemoryTable class
+"""
+
+__version__ = "$Revision: 1662 $"
+# $Source$
+# $Id: test_memory_table.py 1662 2003-08-27 13:51:01Z bh $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.table import MemoryTable, \
+     FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING
+import dbflib
+
+
+
+class TestMemoryTable(unittest.TestCase):
+
+    def setUp(self):
+        """Create a new dbf file. The name is in self.filename"""
+        self.table = MemoryTable([("type", FIELDTYPE_STRING),
+                                  ("value", FIELDTYPE_DOUBLE),
+                                  ("code", FIELDTYPE_INT)],
+                                 [("UNKNOWN", 0.0, 0),
+                                  ("Foo", 0.5, -1),
+                                  ("Foo", 0.25, 100),
+                                  ("bar", 1e10, 17)])
+
+    def test_num_rows(self):
+        """Test MemoryTable.NumRows()"""
+        self.assertEquals(self.table.NumRows(), 4)
+
+    def test_num_columns(self):
+        """Test MemoryTable.NumColumns()"""
+        self.assertEquals(self.table.NumColumns(), 3)
+
+    def test_columns(self):
+        """Test MemoryTable.Columns()"""
+        columns = self.table.Columns()
+        self.assertEquals(columns[0].name, "type")
+        self.assertEquals(columns[0].type, FIELDTYPE_STRING)
+        self.assertEquals(columns[1].name, "value")
+        self.assertEquals(columns[1].type, FIELDTYPE_DOUBLE)
+        self.assertEquals(columns[2].name, "code")
+        self.assertEquals(columns[2].type, FIELDTYPE_INT)
+
+    def test_column(self):
+        """Test MemoryTable.Column()"""
+        # The Column method can be called with either an index or a name
+        col = self.table.Column(2)
+        self.assertEquals(col.name, "code")
+        self.assertEquals(col.type, FIELDTYPE_INT)
+        col = self.table.Column("value")
+        self.assertEquals(col.name, "value")
+        self.assertEquals(col.type, FIELDTYPE_DOUBLE)
+
+    def test_has_column(self):
+        """Test MemoryTable.HasColumn()"""
+        # HasColumn
+        self.failUnless(self.table.HasColumn("value"))
+        self.failUnless(self.table.HasColumn(2))
+        # HasColumn for non-exisiting columns
+        self.failIf(self.table.HasColumn("non_existing_name"))
+        self.failIf(self.table.HasColumn(100))
+
+    def test_read_row_as_dict(self):
+        """Test MemoryTable.ReadRowAsDict()"""
+        self.assertEquals(self.table.ReadRowAsDict(1),
+                          {"type": "Foo", "value": 0.5, "code": -1})
+
+    def test_read_row_as_dict_row_count_mode(self):
+        """Test MemoryTable.ReadRowAsDict() row count address mode"""
+        self.assertEquals(self.table.ReadRowAsDict(1, row_is_ordinal = 1),
+                          {"type": "Foo", "value": 0.5, "code": -1})
+
+    def test_read_value(self):
+        """Test MemoryTable.ReadValue()"""
+        # The column in ReadValue may be given as either name or index
+        self.assertEquals(self.table.ReadValue(2, 0), "Foo")
+        self.assertEquals(self.table.ReadValue(3, "code"), 17)
+
+    def test_read_value_row_count_mode(self):
+        """Test MemoryTable.ReadValue() row count address mode"""
+        # The column in ReadValue may be given as either name or index
+        self.assertEquals(self.table.ReadValue(2, 0, row_is_ordinal = 1),
+                          "Foo")
+        self.assertEquals(self.table.ReadValue(3, "code", row_is_ordinal=1),
+                          17)
+
+    def test_row_id_to_ordinal(self):
+        """Test MemoryTable.RowIdToOrdinal()"""
+        self.assertEquals(self.table.RowIdToOrdinal(5), 5)
+
+    def test_row_oridnal_to_id(self):
+        """Test MemoryTable.RowOrdinalToId()"""
+        self.assertEquals(self.table.RowOrdinalToId(5), 5)
+
+    def test_value_range(self):
+        """Test MemoryTable.ValueRange()"""
+        self.assertEquals(self.table.ValueRange("code"), (-1, 100))
+        self.assertEquals(self.table.ValueRange(1), (0, 1e10))
+
+    def test_unique_values(self):
+        """Test MemoryTable.UniqueValues()"""
+        # The column can be specified by name or index
+        self.assertEquals(self.table.UniqueValues("type"),
+                          ["Foo", "UNKNOWN", "bar"])
+        self.assertEquals(self.table.UniqueValues(2), [-1, 0, 17, 100])
+
+    def test_write(self):
+        """Test MemoryTable.write_record()"""
+        # change only one field
+        # TODO: acticate when implemented
+        # table.write_record(2, {"type": "FARMS"})
+
+        # check whether the table returns the new value
+        # TODO: acticate when implemented
+        #eq(table.read_record(2),
+        #   {'type': "FARMS", "height": 400.44, "code": 2})
+
+        # Check whether we can specify the record as a tuple
+        self.table.write_record(3, ("HUTS", 111.11, 42))
+        self.assertEquals(self.table.ReadRowAsDict(3),
+                          {"type": "HUTS", "value": 111.11, "code": 42})
+
+    def test_dependencies(self):
+        """Test MemoryTable.Dependencies()"""
+        # A MemoryTable doesn't have dependencies
+        self.assertEquals(len(self.table.Dependencies()), 0)
+
+    def test_title(self):
+        """Test MemoryTable.Title()"""
+        self.assertEquals(self.table.Title(), "MemoryTable")
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_menu.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_menu.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_menu.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,122 @@
+# Copyright (c) 2002 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Menu
+"""
+
+__version__ = "$Revision: 2205 $"
+# $Source$
+# $Id: test_menu.py 2205 2004-05-12 20:50:33Z jan $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.UI.menu import Menu
+
+
+class MenuTest(unittest.TestCase):
+
+    def compare_menus(self, menu1, menu2):
+        eq = self.assertEquals
+        ass = self.assert_
+        ass(isinstance(menu1, Menu))
+        ass(isinstance(menu2, Menu))
+        eq(menu1.name, menu2.name)
+        self.compare_items(menu1.items, menu2.items)
+
+    def compare_items(self, items1, items2):
+        eq = self.assertEquals
+        eq(len(items1), len(items2), "Item lists have different lengths")
+        for i in range(len(items1)):
+            i1 = items1[i]
+            i2 = items2[i]
+            if isinstance(i1, Menu):
+                self.compare_menus(i1, i2)
+            else:
+                eq(i1, i2)
+
+    def test(self):
+        """Menu operations (adding new items and submenus)"""
+        eq = self.assertEquals
+
+        # Build a typical main menu for an application. Here we have
+        # only the file menu as sub-menu at first.
+        # Make sure we copy the file_items list so that it won't be
+        # modified
+        file_items = ["new", None, "open", "save"]
+        menu = Menu("<main>", "<main>",
+                    [Menu("file", "File", file_items[:])])
+
+        # fetch the file submenu
+        filemenu = menu.find_menu("file")
+        # check whether it's the right one
+        self.compare_menus(filemenu, Menu("file", "File", file_items[:]))
+
+        # append a separator and an item to the file menu
+        filemenu.InsertSeparator()
+        filemenu.InsertItem("exit")
+        file_items.extend([None, "exit"])
+        self.compare_menus(filemenu, Menu("file", "File", file_items[:]))
+
+        # append an item to the file menu
+        filemenu.InsertItem("save_as", after="save")
+        file_items.insert(4, "save_as")
+        self.compare_menus(filemenu, Menu("file", "File", file_items[:]))
+
+        # add a new sub-menu to the main menu
+        help_items = ["about", "manual"]
+        helpmenu = menu.InsertMenu("help", "Help")
+        helpmenu.SetItems(help_items[:])
+
+        self.compare_menus(menu, Menu("<main>", "<main>",
+                                      [Menu("file", "File", file_items[:]),
+                                       Menu("help", "Help", help_items[:])]))
+
+        self.compare_menus(helpmenu, Menu("help", "Help", help_items[:]))
+
+        # add new sub-menu after the file menu but before the help menu
+        edit_items = ["cut", "copy", "paste"]
+        editmenu = menu.InsertMenu("edit", "Edit", after="file")
+        editmenu.SetItems(edit_items[:])
+
+        self.compare_menus(editmenu, Menu("edit", "Edit", edit_items[:]))
+        self.compare_menus(menu, Menu("<main>", "<main>",
+                                      [Menu("file", "File", file_items[:]),
+                                       Menu("edit", "Edit", edit_items[:]),
+                                       Menu("help", "Help", help_items[:])]))
+
+        # remove an item from the menu
+        self.compare_menus(editmenu, Menu("edit", "Edit", edit_items[:]))
+        editmenu.RemoveItem("copy")
+        self.compare_menus(editmenu, Menu("edit", "Edit", ['cut', 'paste']))
+        editmenu.InsertItem("copy", after="cut") # for convenience for
+                                                 # the following tests
+
+        # find-or-insert a menu
+        self.compare_menus(menu, Menu("<main>", "<main>",
+                                      [Menu("file", "File", file_items[:]),
+                                       Menu("edit", "Edit", edit_items[:]),
+                                       Menu("help", "Help", help_items[:])]))
+        menu.FindOrInsertMenu("extensions", "Extensions")
+        self.compare_menus(menu, Menu("<main>", "<main>",
+                                      [Menu("file", "File", file_items[:]),
+                                       Menu("edit", "Edit", edit_items[:]),
+                                       Menu("help", "Help", help_items[:]),
+                                       Menu("extensions", "Extensions", [])]))
+        menu.FindOrInsertMenu("extensions", "Extensions")
+        self.compare_menus(menu, Menu("<main>", "<main>",
+                                      [Menu("file", "File", file_items[:]),
+                                       Menu("edit", "Edit", edit_items[:]),
+                                       Menu("help", "Help", help_items[:]),
+                                       Menu("extensions", "Extensions", [])]))
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/test/test_mockgeo.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_mockgeo.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_mockgeo.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,47 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Test cases for the mockgeo helper objects"""
+
+__version__ = "$Revision: 1585 $"
+# $Source$
+# $Id: test_mockgeo.py 1585 2003-08-15 10:26:40Z bh $
+
+import unittest
+
+import mockgeo
+
+import support
+
+class TestAffineProjection(unittest.TestCase, support.FloatComparisonMixin):
+
+    def test_forward(self):
+        """Test AffineProjection.Forward()"""
+        proj = mockgeo.AffineProjection((0.25, 0.1, 2, 0.125, 100.75, 123.25))
+        self.assertEquals(proj.Forward(0, 0), (100.75, 123.25))
+        self.assertEquals(proj.Forward(10.0, 20.0), (143.25, 126.75))
+        self.assertEquals(proj.Forward(30, 0.125), (108.5, 126.265625))
+
+    def test_inverse(self):
+        """Test AffineProjection.Inverse()"""
+        proj = mockgeo.AffineProjection((0.25, 0.1, 2, 0.125, 100.75, 123.25))
+        self.assertEquals(proj.Inverse(100.75, 123.25), (0, 0))
+        self.assertEquals(proj.Inverse(143.25, 126.75), (10.0, 20.0))
+        self.assertFloatSeqEqual(proj.Inverse(108.5, 126.265625), (30, 0.125))
+
+    def test_int_coeff(self):
+        """Test AffineProjection with integer coefficients"""
+        proj = mockgeo.AffineProjection((1, 1, -1, 1, 0, 0))
+        # The determinant is an int too but must be treated as a float
+        # when dividing by it otherwise some coefficients in the inverse
+        # become wrong.
+        self.assertEquals(proj.Inverse(10, 10), (10, 0))
+
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_postgis_db.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_postgis_db.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_postgis_db.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,931 @@
+# Copyright (C) 2003, 2004, 2005, 2006 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Test for Thuban.Model.postgisdb"""
+
+import os
+import unittest
+
+
+try:
+    import psycopg
+except ImportError:
+    # No psycopg available. Nothing to be done here because the
+    # postgis.py support module determines this too and the tests will
+    # be skipped completely.
+    pass
+
+import postgissupport
+
+import support
+support.initthuban()
+
+from Thuban.Model.postgisdb import ConnectionError, PostGISConnection, \
+     PostGISTable, PostGISShapeStore
+from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_STRING, \
+     FIELDTYPE_DOUBLE
+from Thuban.Model.data import SHAPETYPE_POINT, SHAPETYPE_POLYGON, \
+     SHAPETYPE_ARC, RAW_WKT
+
+
+class NonConnection(PostGISConnection):
+
+    """Special connection class that doesn't actually connect"""
+
+    def connect(self):
+        pass
+
+
+
+class TestPostGISSimple(unittest.TestCase):
+
+    """Some simple PostGISConnection tests that don't need a real connection"""
+
+    def test_brief_description(self):
+        """Test PostGISConnection.BriefDescription()"""
+        self.assertEquals(NonConnection("somedb").BriefDescription(),
+                          "postgis://@:/somedb")
+        self.assertEquals(NonConnection("db", host="here",
+                                        port="123").BriefDescription(),
+                          "postgis://@here:123/db")
+        self.assertEquals(NonConnection("db", user="me",
+                                        port="123").BriefDescription(),
+                          "postgis://me@:123/db")
+
+    def test_matches_parameters(self):
+        """Test PostGISConnection.MatchesParameters()"""
+        def do_test(testfn, conn, host = "", port="", dbname = "", user = ""):
+            testfn(conn.MatchesParameters({"host": host, "port": port,
+                                           "dbname": dbname, "user": user}))
+
+        do_test(self.assert_, NonConnection("somedb"),
+                dbname="somedb")
+        do_test(self.assert_, NonConnection("somedb", host="here"),
+                dbname="somedb", host="here")
+        do_test(self.assert_, NonConnection("db", user="me", port="123"),
+                dbname="db", port="123", user="me")
+
+        do_test(self.failIf, NonConnection("somedb"),
+                dbname="someotherdb")
+        do_test(self.failIf, NonConnection("somedb", host="here"),
+                dbname="somedb", host="here", port="765")
+        do_test(self.failIf, NonConnection("db", user="me", port="123"),
+                dbname="db", port="123", user="you")
+
+
+class TestPostGISConnection(unittest.TestCase):
+
+    def setUp(self):
+        """Start the server and create a database.
+
+        The database name will be stored in self.dbname, the server
+        object in self.server and the db object in self.db.
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.dbname = ".".join(self.id().split(".")[-2:])[-31:]
+        self.db = self.server.new_postgis_db(self.dbname)
+
+    def test_gis_tables_empty(self):
+        """Test PostGISConnection.GISTables() on empty DB"""
+        db = PostGISConnection(dbname = self.dbname,
+                               **self.server.connection_params("user"))
+
+        # An empty database doesn't have any GIS tables
+        self.assertEquals(db.GeometryTables(), [])
+
+    def test_gis_tables_with_views_and_tables(self):
+        db = PostGISConnection(dbname = self.dbname,
+                               **self.server.connection_params("user"))
+
+        conn = psycopg.connect("dbname=%s " % self.dbname
+                               + self.server.connection_string("admin"))
+        cursor = conn.cursor()
+        # First a normal table, i.e. one without a geometry column
+        # we need an explicit WITH OIDS for postgresql >= 8.0
+        cursor.execute("CREATE TABLE normal (A INT, B VARCHAR) WITH OIDS;"
+                       "GRANT SELECT ON normal TO PUBLIC;")
+
+        # Then a table with a geometry column
+        # we need an explicit WITH OIDS for postgresql >= 8.0
+        cursor.execute("CREATE TABLE geo (A INT) WITH OIDS;"
+                       "GRANT SELECT ON geo TO PUBLIC;")
+        cursor.execute("SELECT AddGeometryColumn(%(dbname)s, 'geo',"
+                       " 'the_geom', -1, 'POINT', 2);",
+                       {"dbname": self.dbname})
+
+        # And create a view containing a geometry column
+        cursor.execute("CREATE VIEW my_view AS"
+                       " (SELECT * FROM geo WHERE a > 100);"
+                       "GRANT SELECT ON my_view TO PUBLIC;")
+        conn.commit()
+
+        self.assertEquals(db.GeometryTables(), ["geo", "my_view"])
+        self.assertEquals(db.table_columns("geo"),
+                          [("oid", FIELDTYPE_INT), ("a", FIELDTYPE_INT),
+                           ("the_geom", "geometry")])
+        self.assertEquals(db.table_columns("my_view"),
+                          [("a", FIELDTYPE_INT), ("the_geom", "geometry")])
+        self.assertEquals(db.table_columns("normal"),
+                          [("oid", FIELDTYPE_INT), ("a", FIELDTYPE_INT),
+                           ("b", FIELDTYPE_STRING)])
+
+
+class TestPostgisDBExceptions(unittest.TestCase):
+
+    def setUp(self):
+        """Start the postgis server and switch on authentication"""
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.postgisdb = self.server.get_default_static_data_db()
+        self.server.require_authentication(True)
+
+    def tearDown(self):
+        """Extend the inherited method to switch off postgresql authentication
+        """
+        self.server.require_authentication(False)
+
+    def test_no_password(self):
+        """Test PostGISConnection with omitted but required password"""
+        connection_params = self.server.connection_params("user")
+        # remove the password deliberately
+        del connection_params["password"]
+
+        self.assertRaises(ConnectionError,
+                          PostGISConnection, dbname = self.postgisdb.dbname,
+                          **connection_params)
+
+
+class TestPostGISSpecialCases(unittest.TestCase):
+
+    """Tests for special cases of PostGIS table usage"""
+
+    def setUp(self):
+        """Start the server and create a database.
+
+        The database name will be stored in self.dbname, the server
+        object in self.server and the db object in self.db.
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.dbname = ".".join(self.id().split(".")[-2:])[-31:]
+        self.db = self.server.new_postgis_db(self.dbname)
+
+    def test_unsupported_types(self):
+        """test PostGISTable on a table with unsupported data types"""
+        stmt = """CREATE TABLE foo (
+                        gid integer,
+                        ignored bigint,
+                        length float);
+                  GRANT SELECT ON foo TO PUBLIC;
+                  """
+        self.server.execute_sql(self.dbname, "admin", stmt)
+
+        db = PostGISConnection(dbname = self.dbname,
+                               **self.server.connection_params("user"))
+        table = PostGISTable(db, "foo")
+
+        # The bigint column will be ignored because it's not mapped to a
+        # known integer type, so there are only two colunns
+        self.assertEquals(table.NumColumns(), 2)
+        self.assertEquals(table.Column(0).name, "gid")
+        self.assertEquals(table.Column(1).name, "length")
+
+    def test_table_name_quoting(self):
+        """Test whether PostGISTable quotes table names properly"""
+        stmt = '''CREATE TABLE "name with ""quotes"" and spaces" (gid integer);
+             GRANT SELECT ON "name with ""quotes"" and spaces" TO PUBLIC;'''
+        self.server.execute_sql(self.dbname, "admin", stmt)
+
+        db = PostGISConnection(dbname = self.dbname,
+                               **self.server.connection_params("user"))
+        table = PostGISTable(db, 'name with "quotes" and spaces')
+
+        self.assertEquals(table.NumColumns(), 1)
+        self.assertEquals(table.Column(0).name, "gid")
+
+    def test_column_name_quoting(self):
+        """Test whether PostGISTable quotes column names properly"""
+        stmt = '''CREATE TABLE unusual_column_names (
+                     gid integer,
+                     "with space" float,
+                     "with "" quote" integer);
+             INSERT INTO unusual_column_names VALUES (1, 1.0, 0);
+             INSERT INTO unusual_column_names VALUES (2, 2.0, 1);
+             INSERT INTO unusual_column_names VALUES (3, 3.0, 1);
+             GRANT SELECT ON unusual_column_names TO PUBLIC;'''
+        self.server.execute_sql(self.dbname, "admin", stmt)
+
+        db = PostGISConnection(dbname = self.dbname,
+                               **self.server.connection_params("user"))
+        table = PostGISTable(db, 'unusual_column_names')
+
+        self.assertEquals(table.NumColumns(), 3)
+        self.assertEquals(table.Column(0).name, "gid")
+        self.assertEquals(table.Column(1).name, "with space")
+        self.assertEquals(table.Column(2).name, "with \" quote")
+
+        # do some queries where the names have to be quoted
+        self.assertEquals(table.ReadRowAsDict(1),
+                          {"gid": 1, "with space": 1.0, "with \" quote": 0})
+        self.assertEquals(table.ReadValue(2, 1, row_is_ordinal = True), 3.0)
+        self.assertEquals(table.ReadValue(2, 1, row_is_ordinal = False), 2.0)
+        self.assertEquals(table.ValueRange("with space"), (1.0, 3.0))
+
+        # The return value of UniqueValues is unsorted, so we need to
+        # sort it for comparison.
+        unique_values = table.UniqueValues("with \" quote")
+        unique_values.sort()
+        self.assertEquals(unique_values, [0, 1])
+        self.assertEquals(table.SimpleQuery(table.Columns()[2], "==", 1),
+                          [2, 3])
+        self.assertEquals(table.SimpleQuery(table.Columns()[0], "==",
+                                            table.Columns()[1]), [1, 2, 3])
+
+    def test_shapestore_name_quoting(self):
+        """Test whether PostGISShapeStore quotes table names properly"""
+        postgissupport.skip_if_addgeometrycolumn_does_not_use_quote_ident()
+
+        # Create a table with a name that needs quoting and a geometry
+        # column whose name has to be quoted
+        stmt = '''CREATE TABLE "table "" name" (gid integer);
+             GRANT SELECT ON "table "" name" TO PUBLIC;'''
+        self.server.execute_sql(self.dbname, "admin", stmt)
+        stmt = """select AddGeometryColumn('%s', 'table \" name',
+                                           'the \" geom', '-1', 'POINT', 2);"""
+        self.server.execute_sql(self.dbname, "admin", stmt % self.dbname)
+        stmt = '''INSERT INTO "table "" name" VALUES (0,
+                GeometryFromText('POINT(0 0)', -1));'''
+        self.server.execute_sql(self.dbname, "admin", stmt)
+
+        # Instantiate the table
+        db = PostGISConnection(dbname = self.dbname,
+                               **self.server.connection_params("user"))
+        store = PostGISShapeStore(db, "table \" name")
+
+        # do some queries where the names have to be quoted
+        self.assertEquals(store.NumShapes(), 1)
+        self.assertEquals(store.ShapeType(), SHAPETYPE_POINT)
+        self.assertEquals(store.BoundingBox(), (0, 0, 0, 0))
+        self.assertEquals(store.Shape(0).ShapeID(), 0)
+        self.assertEquals([s.ShapeID() for s in store.AllShapes()], [0])
+        self.assertEquals([s.ShapeID()
+                           for s in store.ShapesInRegion((-1, -1, 1, 1))], [0])
+
+    def test_shapestore_empty_table(self):
+        """Test PostGISShapeStore with emtpy table"""
+        conn = psycopg.connect("dbname=%s " % self.dbname
+                               + self.server.connection_string("admin"))
+        cursor = conn.cursor()
+        cursor.execute("CREATE TABLE test (A INT);")
+        cursor.execute("SELECT AddGeometryColumn(%(dbname)s, 'test',"
+                       " 'geometry', -1, 'POINT', 2);",
+                       {"dbname": self.dbname})
+        cursor.execute("GRANT SELECT ON test TO PUBLIC;")
+        conn.commit()
+
+        db = PostGISConnection(dbname = self.dbname,
+                               **self.server.connection_params("user"))
+        store = PostGISShapeStore(db, "test")
+        self.assertEquals(store.BoundingBox(), None)
+
+    def test_shapestore_two_geom_cols(self):
+        """Test PostGISShapeStore with two geometry columns"""
+        conn = psycopg.connect("dbname=%s " % self.dbname
+                               + self.server.connection_string("admin"))
+        cursor = conn.cursor()
+        cursor.execute("INSERT INTO spatial_ref_sys VALUES"
+                       " (1, '', 1, '', 'proj=longlat datum=WGS84')")
+        cursor.execute("INSERT INTO spatial_ref_sys VALUES"
+                       " (2, '', 2, '', 'proj=longlat datum=WGS84')")
+
+        cursor.execute("CREATE TABLE two_geom_cols"
+                       " (gid INTEGER PRIMARY KEY);")
+        cursor.execute("SELECT AddGeometryColumn(%(dbname)s, 'two_geom_cols',"
+                       " 'point', 1, 'POINT', 2);",
+                       {"dbname": self.dbname})
+        cursor.execute("SELECT AddGeometryColumn(%(dbname)s, 'two_geom_cols',"
+                       " 'poly', 2, 'POLYGON', 2);",
+                       {"dbname": self.dbname})
+        cursor.execute("INSERT INTO two_geom_cols(gid, point, poly) VALUES (1,"
+                       " GeometryFromText('POINT(1 1)', 1),"
+                       " GeometryFromText('POLYGON((1 1, 1 2, 2 2,1 1))',2));")
+        cursor.execute("GRANT SELECT ON two_geom_cols TO PUBLIC;")
+        conn.commit()
+
+        db = PostGISConnection(dbname = self.dbname,
+                               **self.server.connection_params("user"))
+
+        # The table has two geometry columns, and will raise a TypeError
+        # when instantiated without specifying which one to use.
+        self.assertRaises(TypeError,
+                          PostGISShapeStore, db, "two_geom_cols")
+
+        # If the geometry_column is not really a geometry column, we get
+        # a TypeError
+        self.assertRaises(TypeError,
+                          PostGISShapeStore, db, "two_geom_cols",
+                          geometry_column = "gid")
+
+        # Instantiate two shape stores, one for each of the geometry
+        # columns, and test whether they determine the right shape types
+        # and srids (getting the srid wrong would lead to an exception
+        # in ShapesInRegion).
+        store = PostGISShapeStore(db, "two_geom_cols",
+                                  geometry_column = "point")
+        self.assertEquals(store.ShapeType(), SHAPETYPE_POINT)
+        self.assertEquals([s.ShapeID()
+                           for s in store.ShapesInRegion((0, 0, 100,100))],
+                          [1])
+
+        store = PostGISShapeStore(db, "two_geom_cols",
+                                  geometry_column = "poly")
+        self.assertEquals(store.ShapeType(), SHAPETYPE_POLYGON)
+        self.assertEquals([s.ShapeID()
+                           for s in store.ShapesInRegion((0, 0, 100,100))],
+                          [1])
+
+
+    def test_simple_error_handling(self):
+        """Test some simple error handling.
+
+        If an error happens in, say the SimpleQuery method, a subsequent
+        ReadValue call should still succeed.
+        """
+        conn = psycopg.connect("dbname=%s " % self.dbname
+                               + self.server.connection_string("admin"))
+        cursor = conn.cursor()
+        cursor.execute("CREATE TABLE some_table"
+                       " (gid INTEGER PRIMARY KEY, length float);"
+                       "INSERT INTO some_table VALUES (1, 3.5);")
+        cursor.execute("GRANT SELECT ON some_table TO PUBLIC;")
+        conn.commit()
+        conn.close()
+
+        db = PostGISConnection(dbname = self.dbname,
+                               **self.server.connection_params("user"))
+        table = PostGISTable(db, "some_table", id_column = "gid")
+
+        # trying to compare the length to a string should fail with an
+        # exception.
+        self.assertRaises(psycopg.ProgrammingError,
+                          table.SimpleQuery,
+                          table.Column("length"), "<=", "abc")
+
+        # After the exception, doing a query on the same table should
+        # work. Since it's the same database connection as before, it
+        # can fail if no rollback has been done or the connection isn't
+        # in autocommit mode.  Typical error message is
+        #
+        #     ERROR: current transaction is aborted, commands ignored
+        #     until end of transaction block
+        try:
+            self.assertEquals(table.ReadValue(1, "length"), 3.5)
+        except psycopg.ProgrammingError, val:
+            self.fail("table didn't handle exception properly (%s)" % val)
+
+
+class PostGISStaticTests(unittest.TestCase, support.FloatComparisonMixin):
+
+    """Base class for PostGIS tests with static data."""
+
+    def setUp(self):
+        """Start the server and create a database with static data
+
+        This method sets the following instance attributes:
+
+           dbname -- the name of the database
+
+           server -- The server object
+
+           db -- the PostGISConnection object
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.postgisdb = self.server.get_default_static_data_db()
+        self.db = PostGISConnection(dbname = self.postgisdb.dbname,
+                                    **self.server.connection_params("user"))
+
+    def tearDown(self):
+        """Close the database connection"""
+        self.db.Close()
+
+
+class TableTests:
+
+    """Mix-in class for the PostGISTable tests
+
+    The tests defined here make some assumptions about the table and the
+    data in it:
+
+        self.table should be the PostGISTable instance to test.  Derived
+        classes should set this up in setUp.
+
+        self.db should be the DB connection object used by self.table.
+
+        self.table_name should be the name of the table in the database.
+        The tests assume that e.g. the title of self.table can be
+        derived from this.
+
+        self.gid_column should be the name of the gid column used when
+        self.table was instantiated.
+
+        The data in the table should be the data of the
+        cultural_landmark-point shapefile with the shape ids used to get
+        the contents of the gid column by adding 1000.
+    """
+
+    def test_dbconn(self):
+        """Test PostGISTable.DBConnection()"""
+        self.failUnless(self.table.DBConnection() is self.db)
+
+    def test_dbname(self):
+        """Test PostGISTable.TableName()"""
+        self.assertEquals(self.table.TableName(), self.table_name)
+
+    def test_title(self):
+        """test PostGISTable.Title()"""
+        # The title is currently equal to the tablename
+        self.assertEquals(self.table.Title(), self.table_name)
+
+    def test_dependencies(self):
+        """Test PostGISTable.Dependencies()"""
+        # A PostGISTable depends on no other data container
+        self.assertEquals(self.table.Dependencies(), ())
+
+    def test_num_rows(self):
+        """Test PostGISTable.NumRows()"""
+        self.assertEquals(self.table.NumRows(), 34)
+
+    def test_num_columns(self):
+        """Test PostGISTable.NumColumns()"""
+        # The table in the postgis db has one additional column, "gid",
+        # so there's one more column in the PostGISTable than in the DBF
+        self.assertEquals(self.table.NumColumns(), 7)
+
+    def test_columns(self):
+        """Test PostGISTable.Columns()"""
+        self.assertEquals(len(self.table.Columns()), 7)
+        self.assertEquals(self.table.Columns()[0].name, self.gid_column)
+        self.assertEquals(self.table.Columns()[0].type, FIELDTYPE_INT)
+        self.assertEquals(self.table.Columns()[0].index, 0)
+        self.assertEquals(self.table.Columns()[1].name, "area")
+        self.assertEquals(self.table.Columns()[1].type, FIELDTYPE_DOUBLE)
+        self.assertEquals(self.table.Columns()[1].index, 1)
+        self.assertEquals(self.table.Columns()[5].name, "clptlabel")
+        self.assertEquals(self.table.Columns()[5].type, FIELDTYPE_STRING)
+        self.assertEquals(self.table.Columns()[5].index, 5)
+
+    def test_column(self):
+        """Test PostGISTable.Column()"""
+        self.assertEquals(self.table.Column("area").name, "area")
+        self.assertEquals(self.table.Column("area").type, FIELDTYPE_DOUBLE)
+        self.assertEquals(self.table.Column("area").index, 1)
+
+    def test_has_column(self):
+        """Test PostGISTable.HasColumn()"""
+        self.assert_(self.table.HasColumn("area"))
+        self.failIf(self.table.HasColumn("foo"))
+
+    def test_read_row_as_dict(self):
+        """Test PostGISTable.ReadRowAsDict()"""
+        self.assertEquals(self.table.ReadRowAsDict(1003),
+                          {self.gid_column: 1003,
+                           "area": 0.0,
+                           "perimeter": 0.0,
+                           "clpoint_": 4,
+                           "clpoint_id": 24,
+                           "clptlabel": "RUINS",
+                           "clptflag": 0})
+
+    def test_read_row_as_dict_row_count_mode(self):
+        """Test PostGISTable.ReadRowAsDict() row count address mode"""
+        self.assertEquals(self.table.ReadRowAsDict(3, row_is_ordinal = 1),
+                          {self.gid_column: 1003,
+                           "area": 0.0,
+                           "perimeter": 0.0,
+                           "clpoint_": 4,
+                           "clpoint_id": 24,
+                           "clptlabel": "RUINS",
+                           "clptflag": 0})
+
+    def test_read_value(self):
+        """Test PostGISTable.ReadValue()"""
+        self.assertEquals(self.table.ReadValue(1003, 4), 24)
+        self.assertEquals(self.table.ReadValue(1003, "clpoint_id"), 24)
+
+    def test_read_value_row_count_mode(self):
+        """Test PostGISTable.ReadValue() row count address mode"""
+        self.assertEquals(self.table.ReadValue(3, 4, row_is_ordinal = 1), 24)
+        self.assertEquals(self.table.ReadValue(3, "clpoint_id",
+                                               row_is_ordinal = 1),
+                          24)
+
+    def test_row_id_to_ordinal(self):
+        """Test PostGISTable.RowIdToOrdinal()"""
+        self.assertEquals(self.table.RowIdToOrdinal(1005), 5)
+
+    def test_row_oridnal_to_id(self):
+        """Test PostGISTable.RowOrdinalToId()"""
+        self.assertEquals(self.table.RowOrdinalToId(5), 1005)
+
+    def test_value_range(self):
+        """Test PostGISTable.ValueRange()"""
+        self.assertEquals(self.table.ValueRange("clpoint_id"), (21, 74))
+
+    def test_unique_values(self):
+        """Test PostGISTable.UniqueValues()"""
+        values = self.table.UniqueValues("clptlabel")
+        values.sort()
+        self.assertEquals(values, ["BUILDING", "FARM", "HUT","LIGHTHOUSE",
+                                   "OTHER/UNKNOWN", "RUINS"])
+
+    def test_simple_query(self):
+        """Test PostGISTable.SimpleQuery()"""
+        table = self.table
+        self.assertEquals(table.SimpleQuery(table.Column("clptlabel"),
+                                            "==", "FARM"),
+                          [1006])
+        self.assertEquals(table.SimpleQuery(table.Column("clpoint_id"),
+                                            ">", 70),
+                          [1024, 1025, 1026])
+        self.assertEquals(table.SimpleQuery(table.Column("clpoint_id"),
+                                            "<", table.Column("clpoint_")),
+                          [1028, 1029, 1030, 1031, 1032, 1033])
+
+
+class TestPostGISTable(TableTests, PostGISStaticTests):
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISTable"""
+        PostGISStaticTests.setUp(self)
+        self.table_name = "landmarks"
+        self.gid_column = "gid"
+
+        # Note that omit the gid column here to the backwards compatible
+        # interface of the constructor where the gid_column defaults to
+        # "gid"
+        self.table = PostGISTable(self.db, self.table_name)
+
+
+class TestPostGISTableExplicitGIDColumn(TableTests, PostGISStaticTests):
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISTable"""
+        PostGISStaticTests.setUp(self)
+        self.table_name = "landmarks_point_id"
+        self.gid_column = "point_id"
+        self.table = PostGISTable(self.db, self.table_name,
+                                  id_column = self.gid_column)
+
+
+class PointTests:
+
+    """Mix-in class for the tests on POINT tables
+
+    The methods in this class expect self.store to be the shapestore
+    used for testing.  Derived classes should initialize self.store with
+    PostGISShapeStore in setUp.  Another assumption is that the data in
+    self.store is effectively the cultural_landmark-point shapefile with
+    shape ids increased by 1000.
+    """
+
+    #
+    # First, some tests that should be independend of the shapetype, so
+    # it shouldn't be necessary to repeat them for other shapetypes
+    #
+
+    def test_dependencies(self):
+        """Test PostGISShapeStore.Dependencies()"""
+        # A PostGISShapeStore depends on no other data container
+        self.assertEquals(self.store.Dependencies(), ())
+
+    def test_table(self):
+        """Test PostGISShapeStore.Table() with POINT shapes"""
+        # A PostGISShapeStore is its own table
+        self.assert_(self.store.Table() is self.store)
+
+    def test_orig_shapestore(self):
+        """Test PostGISShapeStore.OrigShapeStore() with POINT shapes"""
+        # A PostGISShapeStore is not derived from another shape store
+        self.assert_(self.store.OrigShapeStore() is None)
+
+    def test_raw_format(self):
+        """Test PostGISShapeStore.RawShapeFormat() with POINT shapes"""
+        self.assertEquals(self.store.RawShapeFormat(), RAW_WKT)
+
+    def test_all_shapes(self):
+        """Test PostGISShapeStore.AllShapes()"""
+        self.assertEquals([s.ShapeID() for s in self.store.AllShapes()],
+                          range(1000, 1000 + self.store.NumShapes()))
+
+    def test_id_column(self):
+        self.assertEquals(self.store.IDColumn().name, self.id_column)
+
+    def test_geometry_column(self):
+        self.assertEquals(self.store.GeometryColumn().name,
+                          self.geometry_column)
+
+    #
+    # Shapetype specific tests
+    #
+
+    def test_shape_type(self):
+        """Test PostGISShapeStore.ShapeType() with POINT shapes"""
+        self.assertEquals(self.store.ShapeType(), SHAPETYPE_POINT)
+
+    def test_num_shapes(self):
+        """Test PostGISShapeStore.NumShapes() with POINT shapes"""
+        self.assertEquals(self.store.NumShapes(), 34)
+
+    def test_bounding_box(self):
+        """Test PostGISShapeStore.BoundingBox() with POINT shapes"""
+        self.assertFloatSeqEqual(self.store.BoundingBox(),
+                                 [-23.806047439575195, 63.405960083007812,
+                                  -15.12291431427002, 66.36572265625])
+
+    def test_shape_shapeid(self):
+        """Test PostGISShapeStore.Shape(i).ShapeID() with POINT shapes"""
+        self.assertEquals(self.store.Shape(1005).ShapeID(), 1005)
+
+    def test_shape_points(self):
+        """Test PostGISShapeStore.Shape(i).Points() with POINT shapes"""
+        self.assertPointListEquals(self.store.Shape(1000).Points(),
+                                   [[(-22.711074829101562, 66.36572265625)]])
+
+    def test_shape_raw_data(self):
+        """Test PostGISShapeStore.Shape(i).RawData() with POINT shapes"""
+        self.assertEquals(self.store.Shape(1000).RawData(),
+                          'POINT(-22.7110748291016 66.36572265625)')
+
+    def test_shapes_in_region(self):
+        """Test PostGISShapeStore:ShapesInRegion() with POINT shapes"""
+        shapes = self.store.ShapesInRegion((-20.0, 64.0, -24.0, 67))
+        self.assertEquals([s.ShapeID() for s in shapes],
+                          [1000, 1001, 1002, 1003, 1004, 1005, 1027])
+
+
+class TestPostGISShapestorePoint(PointTests, PostGISStaticTests):
+
+    """Tests for PostGISShapeStore objects with POINT data an no SRID"""
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISShapeStore"""
+        PostGISStaticTests.setUp(self)
+        self.id_column = "gid"
+        self.geometry_column = "the_geom"
+        self.store = PostGISShapeStore(self.db, "landmarks")
+
+
+
+class TestPostGISShapestorePointSRID(PointTests, PostGISStaticTests):
+
+    """Tests for PostGISShapeStore objects with POINT data and an SRID"""
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISShapeStore"""
+        PostGISStaticTests.setUp(self)
+        self.id_column = "gid"
+        self.geometry_column = "the_geom"
+        self.store = PostGISShapeStore(self.db, "landmarks_srid")
+
+
+class TestPostGISShapestorePointExplicitGIDColumn(PointTests,
+                                                  PostGISStaticTests):
+
+    """Tests for PostGISShapeStores with POINT data and explicit gid column"""
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISShapeStore"""
+        PostGISStaticTests.setUp(self)
+        self.id_column = "point_id"
+        self.geometry_column = "the_geom"
+        self.store = PostGISShapeStore(self.db, "landmarks_point_id",
+                                       id_column = "point_id")
+
+
+class TestPostGISShapestorePointOIDAsGIDColumn(PointTests, PostGISStaticTests):
+
+    """Tests for PostGISShapeStores with POINT data using OID as gid column"""
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISShapeStore"""
+        PostGISStaticTests.setUp(self)
+        self.id_column = "oid"
+        self.geometry_column = "the_geom"
+        self.store = PostGISShapeStore(self.db, "landmarks_point_id",
+                                       id_column = self.id_column,
+                                       geometry_column = self.geometry_column)
+
+    def find_test_shape_id(self):
+        """Return the id of an interesting shape for some test cases.
+
+        This test uses OIDs so we can't easily hard wire ids in the test
+        cases
+        """
+        # get the id of an interesting shape
+        shapes = self.store.ShapesInRegion((-20.0, 64.0, -24.0, 67))
+        return list(shapes)[0].ShapeID()
+
+
+    # Override a few tests that won't work with this table because they
+    # require knowledge of specific IDs
+
+    def test_shape_shapeid(self):
+        """Test PostGISShapeStore.Shape(i).ShapeID() with POINT shapes"""
+        gid = self.find_test_shape_id()
+        self.assertEquals(self.store.Shape(gid).ShapeID(), gid)
+
+    def test_shape_points(self):
+        """Test PostGISShapeStore.Shape(i).Points() with POINT shapes"""
+        gid = self.find_test_shape_id()
+        self.assertPointListEquals(self.store.Shape(gid).Points(),
+                                   [[(-22.711074829101562, 66.36572265625)]])
+
+    def test_shape_raw_data(self):
+        """Test PostGISShapeStore.Shape(i).RawData() with POINT shapes"""
+        gid = self.find_test_shape_id()
+        self.assertEquals(self.store.Shape(gid).RawData(),
+                          'POINT(-22.7110748291016 66.36572265625)')
+
+    def test_shapes_in_region(self):
+        """Test PostGISShapeStore:ShapesInRegion() with POINT shapes"""
+        shapes = self.store.ShapesInRegion((-20.0, 64.0, -24.0, 67))
+        self.assertEquals(len(list(shapes)), 7)
+
+    def test_all_shapes(self):
+        """Test PostGISShapeStore.AllShapes()"""
+        self.assertEquals(len(list(self.store.AllShapes())), 34)
+
+
+class TestPostGISShapestorePointFromViews(PointTests, PostGISStaticTests):
+
+    """Tests for PostGISShapeStores with POINT data in a view"""
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISShapeStore"""
+        PostGISStaticTests.setUp(self)
+        self.id_column = "point_id"
+        self.geometry_column = "the_geom"
+        self.store = PostGISShapeStore(self.db, "v_landmarks",
+                                       id_column = "point_id")
+
+
+class LineStringTests:
+
+    """Tests shared by the LINESTRING and MULTILINESTRING tests.
+
+    The tests are the same because they are based on the same data.
+    """
+
+    def test_shape_type(self):
+        """Test PostGISShapeStore.ShapeType() with ARC shapes"""
+        self.assertEquals(self.store.ShapeType(), SHAPETYPE_ARC)
+
+    def test_num_shapes(self):
+        """Test PostGISShapeStore.NumShapes() with ARC shapes"""
+        self.assertEquals(self.store.NumShapes(), 839)
+
+    def test_bounding_box(self):
+        """Test PostGISShapeStore.BoundingBox() with ARC shapes"""
+        self.assertFloatSeqEqual(self.store.BoundingBox(),
+                                 [-24.450359344482422, 63.426830291748047,
+                                  -13.55668830871582, 66.520111083984375])
+
+    def test_shape_shapeid(self):
+        """Test PostGISShapeStore.Shape(i).ShapeID() with ARC shapes"""
+        self.assertEquals(self.store.Shape(5).ShapeID(), 5)
+
+    def test_shape_points(self):
+        """Test PostGISShapeStore.Shape(i).Points() with ARC shapes"""
+        self.assertPointListEquals(self.store.Shape(32).Points(),
+                                   [[(-15.0821743011474, 66.2773818969726),
+                                     (-15.0263500213623, 66.2733917236328)]])
+
+    def test_shapes_in_region(self):
+        """Test PostGISShapeStore.ShapesInRegion() with ARC shapes"""
+        shapes = self.store.ShapesInRegion((-24.0, 64.5, -23.5, 65.0))
+        self.assertEquals([s.ShapeID() for s in shapes], [573, 581, 613])
+
+
+class TestPostGISShapestoreLineString(LineStringTests, PostGISStaticTests):
+
+    """Tests for PostGISShapeStore objects with LINESTRING data"""
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISShapeStore"""
+        PostGISStaticTests.setUp(self)
+        self.store = PostGISShapeStore(self.db, "roads")
+
+    def test_shape_raw_data(self):
+        """Test PostGISShapeStore.Shape(i).RawData() with ARC shapes"""
+        self.assertEquals(self.store.Shape(32).RawData(),
+                     "LINESTRING(-15.0821743011475 66.2773818969727,"
+                                "-15.0263500213623 66.2733917236328)")
+
+
+class TestPostGISShapestoreMultiLineString(LineStringTests,
+                                           PostGISStaticTests):
+
+    """Tests for PostGISShapeStore objects with MULTILINESTRING data"""
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISShapeStore"""
+        PostGISStaticTests.setUp(self)
+        self.store = PostGISShapeStore(self.db, "roads_multi")
+
+    def test_shape_raw_data(self):
+        """Test PostGISShapeStore.Shape(i).RawData() with ARC shapes"""
+        self.assertEquals(self.store.Shape(32).RawData(),
+                     "MULTILINESTRING((-15.0821743011475 66.2773818969727,"
+                                      "-15.0263500213623 66.2733917236328))")
+
+
+class PolygonTests:
+
+    """Test shared by the POLYGON and MULTIPOLYGON tests
+
+    The tests are the same because they are based on the same data.
+    """
+
+    def test_shape_type(self):
+        """Test PostGISShapeStore.ShapeType() with POLYGON shapes"""
+        self.assertEquals(self.store.ShapeType(), SHAPETYPE_POLYGON)
+
+    def test_num_shapes(self):
+        """Test PostGISShapeStore.NumShapes() with POLYGON shapes"""
+        self.assertEquals(self.store.NumShapes(), 156)
+
+    def test_bounding_box(self):
+        """Test PostGISShapeStore.BoundingBox() with POLYGON shapes"""
+        self.assertFloatSeqEqual(self.store.BoundingBox(),
+                                 [-24.546524047851562, 63.286754608154297,
+                                  -13.495815277099609, 66.563774108886719])
+
+    def test_shape_shapeid(self):
+        """Test PostGISShapeStore.Shape(i).ShapeID() with POLYGON shapes"""
+        self.assertEquals(self.store.Shape(5).ShapeID(), 5)
+
+    def test_shape_points(self):
+        """Test PostGISShapeStore.Shape(i).Points() with POLYGON shapes"""
+        self.assertPointListEquals(self.store.Shape(4).Points(),
+                                   [[(-22.40639114379882, 64.714111328125),
+                                     (-22.41621208190918, 64.716003417968),
+                                     (-22.40605163574218, 64.719200134277),
+                                     (-22.40639114379882, 64.714111328125)]])
+
+    def test_shapes_in_region(self):
+        """Test PostGISShapeStore.ShapesInRegion() with POLYGON shapes"""
+        shapes = self.store.ShapesInRegion((-23.0, 65.5, -22.8, 65.25))
+        self.assertEquals([s.ShapeID() for s in shapes],
+                          [47, 56, 59, 61, 62, 71, 144])
+
+
+class TestPostGISShapestorePolygon(PolygonTests, PostGISStaticTests):
+
+    """Tests for PostGISShapeStore objects with POLYGON data"""
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISShapeStore"""
+        PostGISStaticTests.setUp(self)
+        self.store = PostGISShapeStore(self.db, "political")
+
+    def test_shape_type(self):
+        """Test PostGISShapeStore.ShapeType() with POLYGON shapes"""
+        self.assertEquals(self.store.ShapeType(), SHAPETYPE_POLYGON)
+
+
+    def test_shape_raw_data(self):
+        """Test PostGISShapeStore.Shape(i).RawData() with POLYGON shapes"""
+        self.assertEquals(self.store.Shape(4).RawData(),
+                          "POLYGON((-22.4063911437988 64.714111328125,"
+                                   "-22.4162120819092 64.7160034179688,"
+                                   "-22.4060516357422 64.7192001342773,"
+                                   "-22.4063911437988 64.714111328125))")
+
+
+class TestPostGISShapestoreMultiPolygon(PolygonTests, PostGISStaticTests):
+
+    """Tests for PostGISShapeStore objects with MUTLIPOLYGON data"""
+
+    def setUp(self):
+        """Extend inherited method to set self.table to a PostGISShapeStore"""
+        PostGISStaticTests.setUp(self)
+        self.store = PostGISShapeStore(self.db, "political_multi")
+
+    def test_shape_raw_data(self):
+        """Test PostGISShapeStore.Shape(i).RawData() with POLYGON shapes"""
+        self.assertEquals(self.store.Shape(4).RawData(),
+                          "MULTIPOLYGON(((-22.4063911437988 64.714111328125,"
+                                         "-22.4162120819092 64.7160034179688,"
+                                         "-22.4060516357422 64.7192001342773,"
+                                        "-22.4063911437988 64.714111328125)))")
+
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_postgis_session.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_postgis_session.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_postgis_session.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,132 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Test PostGISConnection and Session interaction"""
+
+__version__ = "$Revision: 1634 $"
+# $Source$
+# $Id: test_postgis_session.py 1634 2003-08-22 16:55:19Z bh $
+
+import unittest
+
+import postgissupport
+import support
+support.initthuban()
+
+from Thuban.Model.postgisdb import PostGISConnection
+from Thuban.Model.session import Session
+from Thuban.Model.messages import DBCONN_ADDED, DBCONN_REMOVED
+
+class TestSessionWithPostGIS(unittest.TestCase, support.SubscriberMixin):
+
+    def setUp(self):
+        """Start the server and create a database.
+
+        The database name will be stored in self.dbname, the server
+        object in self.server and the db object in self.db.
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.dbref = self.server.get_default_static_data_db()
+        self.dbname = self.dbref.dbname
+        self.session = Session("PostGIS Session")
+        self.db = PostGISConnection(dbname = self.dbname,
+                                    **self.server.connection_params("user"))
+
+        self.session.Subscribe(DBCONN_ADDED,
+                               self.subscribe_with_params, DBCONN_ADDED)
+        self.session.Subscribe(DBCONN_REMOVED,
+                               self.subscribe_with_params, DBCONN_REMOVED)
+        self.clear_messages()
+
+    def tearDown(self):
+        self.session.Destroy()
+        self.clear_messages()
+
+    def test_add_dbconn(self):
+        """Test Session.AddDBConnection()"""
+        # Sanity check. No messages should have been generated so far
+        self.check_messages([])
+
+        self.session.AddDBConnection(self.db)
+
+        # After the connection has been added it should show up in the
+        # list returned by DBConnections and a DBCONN_ADDED message
+        # should have been sent
+        self.assertEquals(self.session.DBConnections(), [self.db])
+        self.check_messages([(DBCONN_ADDED,)])
+
+    def test_remove_dbconn(self):
+        """Test Session.RemoveDBConnection()"""
+        self.session.AddDBConnection(self.db)
+        self.clear_messages()
+        self.session.RemoveDBConnection(self.db)
+
+        # After the connection has been added it should not show up in
+        # the list returned by DBConnections any more and a
+        # DBCONN_REMOVED message should have been sent
+        self.assertEquals(self.session.DBConnections(), [])
+        self.check_messages([(DBCONN_REMOVED,)])
+
+    def test_remove_dbconn_exception(self):
+        """Test Session.RemoveDBConnection() with unknown connection"""
+        self.session.AddDBConnection(self.db)
+        self.clear_messages()
+
+        # Trying to remove an unknown connection will raise a
+        # ValueError.
+        self.assertRaises(ValueError, self.session.RemoveDBConnection,
+                          PostGISConnection(dbname = self.dbname,
+                                   **self.server.connection_params("user")))
+        # No message should have been sent when the removal fails
+        self.check_messages([])
+
+    def test_open_db_shapestore(self):
+        """Test Session.OpenDBShapeStore()"""
+        self.session.AddDBConnection(self.db)
+        store = self.session.OpenDBShapeStore(self.db, "landmarks")
+        self.assertEquals(store.NumShapes(), 34)
+
+    def test_remove_dbconn_still_in_use(self):
+        """Test Session.RemoveDBConnection() with connectin still in use"""
+        self.session.AddDBConnection(self.db)
+        store = self.session.OpenDBShapeStore(self.db, "landmarks")
+
+        # Removing a db connection that's still in use raises a
+        # ValueError (not sure the choice of ValueError is really good
+        # here).
+        self.assertRaises(ValueError, self.session.RemoveDBConnection, self.db)
+
+    def test_can_remove_db_con(self):
+        """Test Session.CanRemoveDBConnection()"""
+        self.session.AddDBConnection(self.db)
+        store = self.session.OpenDBShapeStore(self.db, "landmarks")
+
+        # The db connection is in use by store, so CanRemoveDBConnection
+        # should return false
+        self.failIf(self.session.CanRemoveDBConnection(self.db))
+
+        # The only reference to the shapestore is in store, so deleting
+        # the it should remove the weak reference kept by the session so
+        # that afterwards CanRemoveDBConnection should return true
+        del store
+
+        self.failUnless(self.session.CanRemoveDBConnection(self.db))
+
+    def test_has_db_conections(self):
+        """Test Session.HasDBConnections()"""
+        self.failIf(self.session.HasDBConnections())
+
+        self.session.AddDBConnection(self.db)
+        self.failUnless(self.session.HasDBConnections())
+
+        self.session.RemoveDBConnection(self.db)
+        self.failIf(self.session.HasDBConnections())
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_proj.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_proj.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_proj.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,506 @@
+# Copyright (c) 2002, 2003, 2006 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+# Bernhard Reiter <bernhard at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Thuban-specific Projection class
+"""
+
+__version__ = "$Revision: 2698 $"
+# $Source$
+# $Id: test_proj.py 2698 2006-09-18 00:56:26Z bernhard $
+
+import unittest
+import locale
+import os
+
+import localessupport
+import xmlsupport
+import support
+support.initthuban()
+
+from Thuban import _
+from Thuban.Model.proj import Projection, ProjFile, \
+     PROJ_UNITS_METERS, PROJ_UNITS_DEGREES
+from Thuban.Model.messages import PROJECTION_ADDED, PROJECTION_REMOVED, \
+     PROJECTION_REPLACED
+import Thuban.Model.resource as resource
+
+from xmlsupport import sax_eventlist
+
+from xml.sax import SAXParseException
+
+
+class TestProjection(unittest.TestCase, support.FloatComparisonMixin):
+
+    """Test cases for the Thuban-specific Projection class
+    """
+
+    def test(self):
+        """Test Projection"""
+        params = ["zone=26", "proj=utm", "ellps=clrk66"]
+        proj = Projection(params)
+        self.assertEquals(proj.params, params)
+
+        # It's not clear whether this value is really the correct one
+        # but a test failure here probably still means a bug somewhere
+        self.assertFloatSeqEqual(proj.Forward(0, 0),
+                                 [3623101.8103431347, 0.0],
+                                 epsilon = 1e-5)
+        self.assertFloatSeqEqual(proj.Inverse(3623101.8103431347, 0.0),
+                                 [-0.00065775699878736467, 0])
+
+        self.assertFloatSeqEqual(proj.ForwardBBox((0, 0, 2, 2)),
+                                 (3620891.3077618643, 0.0,
+                                  3875381.8535437919, 252962.10480170773),
+                                 epsilon = 1e-5)
+        self.assertFloatSeqEqual(proj.InverseBBox((3620891.3077618643, 0.0,
+                                                   3875381.8535437919,
+                                                   252962.10480170773)),
+                                 (-0.018341599754143501, 0.0,
+                                  2.017992992681688, 2.0377390677846736),
+                                 epsilon = 1e-5)
+
+        # GetName()
+        self.assertEquals(proj.GetName(), _("Unknown"))
+
+        # GetParameter()
+        self.assertEquals(proj.GetParameter("zone"), "26")
+        self.assertEquals(proj.GetParameter("proj"), "utm")
+        self.assertEquals(proj.GetParameter("ellps"), "clrk66")
+        self.assertEquals(proj.GetParameter("hallo"), "")
+
+        # GetAllParameters()
+        self.assertEquals(proj.GetAllParameters(), params)
+
+        # GetName()
+        proj = Projection(params, "MyName")
+        self.assertEquals(proj.GetName(), "MyName")
+
+    def test_get_parameter_without_equals_sign(self):
+        """Test Projection.GetParameter() for a parameter without '=' sign"""
+        proj = Projection(["proj=utm", "zone=34", "south", "ellps=clrk66"])
+        # The Projection class pretends that for parameters specified
+        # without a value the value is the same as the parameter name.
+        self.assertEquals(proj.GetParameter("south"), "south")
+
+    def test_get_projection_units_geo(self):
+        """Test Projection.GetProjectedUnits() for geographic projection.
+        Test for the alias 'longlat' as well.
+        """
+        proj = Projection(["proj=latlong", "to_meter=0.017453292519943295",
+                           "ellps=clrk66"])
+        self.assertEquals(proj.GetProjectedUnits(), PROJ_UNITS_DEGREES)
+        proj = Projection(["proj=longlat", "to_meter=0.017453292519943295",
+                           "ellps=clrk66"])
+        self.assertEquals(proj.GetProjectedUnits(), PROJ_UNITS_DEGREES)
+
+    def test_lc_numeric_robustness(self):
+        """Test if an LC_NUMERIC local with comma as decimal_point will work.
+
+        Some versions of proj are not robust against this.
+        Starting with Python 2.4 there is a different behaviour when
+        calling C extensions and now they will see changes locales settings
+        which might tickle the bug in proj.
+        """
+        params = ["proj=latlong", "to_meter=0.01745", "ellps=clrk66"]
+
+        oldlocale = localessupport.setdecimalcommalocale()
+        if oldlocale == None:
+            raise support.SkipTest(
+                    "No locale with comma as decimal_point found.")
+
+        proj = Projection(params)
+        #print proj.work_around_broken_proj
+        result1 =  proj.Forward(1.2,3.2)
+
+        locale.setlocale(locale.LC_NUMERIC, "C")
+        proj = Projection(params)
+        result2= proj.Forward(1.2,3.2)
+
+        locale.setlocale(locale.LC_NUMERIC, oldlocale)
+        self.assertFloatSeqEqual(result1, result2, epsilon = 1e-5 )
+
+    def test_get_projection_units_normal(self):
+        """Test Projection.GetProjectedUnits() for normal projection"""
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
+        self.assertEquals(proj.GetProjectedUnits(), PROJ_UNITS_METERS)
+
+    def test_label(self):
+        """Test Projection.Label() without epsg"""
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
+                           name = "My Projection")
+        self.assertEquals(proj.Label(), "My Projection")
+
+    def test_label_epsg(self):
+        """Test Projection.Label() with epsg"""
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
+                           name = "My Projection", epsg="42")
+        self.assertEquals(proj.Label(), "EPSG    42 My Projection")
+
+    def test_epsgcode_for_non_epsg_projection(self):
+        """Test Projection.EPSGCode() without epsg"""
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
+                           name = "My Projection")
+        self.assertEquals(proj.EPSGCode(), None)
+
+    def test_epsgcode_for_real_epsg_projection(self):
+        """Test Projection.EPSGCode() with epsg"""
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"],
+                           name = "My Projection", epsg="42")
+        self.assertEquals(proj.EPSGCode(), "42")
+
+
+
+class TestProjFileSimple:
+
+    def test_init(self):
+        """Test ProjFile coinstructor"""
+        proj_file = ProjFile("some_filename")
+        self.assertEquals(proj_file.GetFilename(), "some_filename")
+        self.assertEquals(len(proj_file.GetProjections()), 0)
+
+    def test_set_filename(self):
+        """Test ProjFile.SetFilename()"""
+        proj_file = ProjFile("some_filename")
+        proj.SetFilename("other_name")
+        self.assertEquals(proj_file.GetFilename(), "other_name")
+
+
+class TestProjFile(unittest.TestCase, support.SubscriberMixin):
+
+    """Test cases for ProjFile objects"""
+
+    def setUp(self):
+        self.clear_messages()
+        self.proj0 = Projection(["proj=tmerc", "ellps=clrk66"])
+        self.proj1 = Projection(["proj=utm", "ellps=clrk66"])
+        self.proj2 = Projection(["proj=lcc", "ellps=clrk66",
+                                 "lat_1=0", "lat_2=20"])
+        self.proj_file = ProjFile("some_filename")
+        for msg in [PROJECTION_ADDED, PROJECTION_REMOVED, PROJECTION_REPLACED]:
+            self.proj_file.Subscribe(msg, self.subscribe_with_params, msg)
+
+    def tearDown(self):
+        self.clear_messages()
+        self.proj_file.Destroy()
+
+    def test_add_remove(self):
+        """Test ProjFile.Add() and ProjFile.Remove()"""
+        self.proj_file.Add(self.proj0)
+        self.proj_file.Add(self.proj1)
+        self.assertEquals(self.proj_file.GetProjections(),
+                          [self.proj0, self.proj1])
+        self.check_messages([(self.proj0, PROJECTION_ADDED),
+                             (self.proj1, PROJECTION_ADDED)])
+        self.clear_messages()
+
+        self.proj_file.Remove(self.proj0)
+        self.assertEquals(self.proj_file.GetProjections(), [self.proj1])
+        self.check_messages([(self.proj0, PROJECTION_REMOVED)])
+
+    def test_remove_non_existing(self):
+        """Test ProjFile.Remove(<proj not in projfile>)"""
+        self.assertRaises(ValueError, self.proj_file.Remove, self.proj0)
+        # Nothing happened, so no messages should have been sent
+        self.check_messages([])
+
+    def test_replace(self):
+        """Test ProjFile.Replace()"""
+        self.proj_file.Add(self.proj0)
+        self.proj_file.Add(self.proj1)
+        self.clear_messages()
+
+        # Replace()
+        self.proj_file.Replace(self.proj0, self.proj2)
+        self.assertEquals(self.proj_file.GetProjections(),
+                          [self.proj2, self.proj1])
+        self.check_messages([(self.proj0, self.proj2, PROJECTION_REPLACED)])
+
+    def test_replace_non_existing(self):
+        """Test ProjFile.Replace(<proj not in projfile>, <some proj>)"""
+        self.proj_file.Add(self.proj0)
+        self.proj_file.Add(self.proj1)
+        self.clear_messages()
+        self.assertRaises(ValueError,
+                          self.proj_file.Replace, self.proj2, self.proj0)
+        # All projections should still be there
+        self.assertEquals(self.proj_file.GetProjections(),
+                          [self.proj0, self.proj1])
+        # Nothing happened, so no messages should have been sent
+        self.check_messages([])
+
+
+class ProjFileTest(unittest.TestCase, support.FileTestMixin,
+                   xmlsupport.ValidationTest):
+
+    """Base class for the proj file tests that read or write files"""
+
+    def filename(self):
+        """Return the filename for the test"""
+        return self.temp_file_name(self.id() + ".proj")
+
+
+class ProjFileReadTests(ProjFileTest):
+
+    """Test read ProjFile objects from files
+
+    The files only cover error handling and the system projection file.
+    """
+
+    def test_read_non_existing_file(self):
+        """Test read_proj_file with non-existing file"""
+        self.assertRaises(IOError,
+                          resource.read_proj_file,
+                          self.temp_file_name("nonexistent.proj"))
+
+    def test_read_unreadable_file(self):
+        """Test read_proj_file with unreadable file
+
+        As currently written this only works on unix-like systems and
+        not e.g. on MS Windows.
+        """
+        if os.name != "posix":
+            raise support.SkipTest("Test only works on posix systems")
+        filename = self.filename()
+        file = open(filename, "w")
+        file.close()
+        os.chmod(filename, 0200) # write-only
+        self.assertRaises(IOError, resource.read_proj_file, filename)
+
+    def test_read_empty_file(self):
+        """Test read_proj_file with empty file"""
+        filename = self.filename()
+        file = open(filename, "w")
+        file.close()
+
+        self.assertRaises(SAXParseException, resource.read_proj_file, filename)
+
+    def test_get_system_proj_file(self):
+        """Test resource.get_system_proj_file(DEFAULT_PROJ_FILE)
+
+        This is primarily to test whether the system proj file contains
+        invalid projection paramers and whether the proj file is not
+        empty
+        """
+        projfile, warnings\
+                  = resource.get_system_proj_file(resource.DEFAULT_PROJ_FILE)
+        self.assertEquals(warnings, [])
+        self.assert_(len(projfile.GetProjections()) > 0)
+
+        # see whether it got cached and we get the same projfile object
+        # when we read the file again
+        projfile2, warnings \
+                   = resource.get_system_proj_file(resource.DEFAULT_PROJ_FILE)
+        self.assert_(projfile is projfile2)
+
+
+class WriteProjFileTests(ProjFileTest):
+
+    """Test cases for writing proj files"""
+
+    def compare_xml(self, xml1, xml2):
+        self.assertEquals(sax_eventlist(xml1), sax_eventlist(xml2))
+
+    def doTestWrite(self, projfile, expected):
+        filename = self.filename()
+
+        resource.write_proj_file(projfile)
+
+        file = open(filename)
+        written_contents = file.read()
+        file.close()
+        self.compare_xml(written_contents, expected)
+        self.validate_data(written_contents)
+        self.validate_data(expected)
+
+    def test_write(self):
+        """Test write_proj_file"""
+        pf = ProjFile(self.filename())
+        pf.Add(Projection(['proj=tmerc', 'ellps=clrk66',
+                           'lat_0=90w', 'lon_0=90w', 'k=1'],
+                          "Transverse Mercator",))
+        pf.Add(Projection(["proj=tmerc",
+                           "lat_0=0.000000000", "lon_0=-62.000000000",
+                           "k=0.999500", "x_0=400000.000", "y_0=0.000",
+                           "ellps=clrk80", "units=m"],
+                          "Anguilla 1957 / British West Indies Grid",
+                          epsg="200"))
+        file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+        <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
+        <projectionlist>
+            <projection name="Transverse Mercator">
+                <parameter value="proj=tmerc"/>
+                <parameter value="ellps=clrk66"/>
+                <parameter value="lat_0=90w"/>
+                <parameter value="lon_0=90w"/>
+                <parameter value="k=1"/>
+            </projection>
+            <projection epsg="200"
+                        name="Anguilla 1957 / British West Indies Grid">
+                <parameter value="proj=tmerc"/>
+                <parameter value="lat_0=0.000000000"/>
+                <parameter value="lon_0=-62.000000000"/>
+                <parameter value="k=0.999500"/>
+                <parameter value="x_0=400000.000"/>
+                <parameter value="y_0=0.000"/>
+                <parameter value="ellps=clrk80"/>
+                <parameter value="units=m"/>
+            </projection>
+        </projectionlist>
+        '''
+        self.doTestWrite(pf, file_contents)
+
+    def test_write_empty_file(self):
+        """Test write empty ProjFile"""
+        pf = ProjFile(self.filename())
+        file_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+        <!DOCTYPE projectionlist SYSTEM "projfile.dtd">
+        <projectionlist>
+        </projectionlist>
+        '''
+        self.doTestWrite(pf, file_contents)
+
+
+class ProjFileLoadTestCase(support.FileLoadTestCase):
+
+    """Base class for the test cases that read specific test files"""
+
+    file_extension = ".proj"
+
+    def tearDown(self):
+        """Clear the cache explicitly"""
+        resource.clear_proj_file_cache()
+
+
+class TestLoadingProjFile(ProjFileLoadTestCase):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE projectionlist SYSTEM "projfile.dtd">
+<projectionlist>
+    <projection name="Transverse Mercator">
+        <parameter value="proj=tmerc"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="lat_0=90w"/>
+        <parameter value="lon_0=90w"/>
+        <parameter value="k=1"/>
+    </projection>
+    <projection epsg="200" name="Anguilla 1957 / British West Indies Grid">
+        <parameter value="proj=tmerc"/>
+        <parameter value="lat_0=0.000000000"/>
+        <parameter value="lon_0=-62.000000000"/>
+        <parameter value="k=0.999500"/>
+        <parameter value="x_0=400000.000"/>
+        <parameter value="y_0=0.000"/>
+        <parameter value="ellps=clrk80"/>
+        <parameter value="units=m"/>
+    </projection>
+</projectionlist>
+'''
+
+    def check_projection(self, proj, label, parameters):
+        """Check the values of the proj's label and parameters"""
+        self.assertEquals(proj.Label(), label)
+        params = proj.GetAllParameters()[:]
+        params.sort()
+        self.assertEquals(params, parameters)
+
+    def test(self):
+        projfile, warnings = resource.read_proj_file(self.filename())
+        # no warnings
+        self.assertEquals(warnings, [])
+
+        # There are two projections
+        projs = projfile.GetProjections()
+        self.assertEquals(len(projs), 2)
+
+        self.check_projection(projs[0],
+                              "Transverse Mercator",
+                              ['ellps=clrk66', 'k=1', 'lat_0=90w', 'lon_0=90w',
+                               'proj=tmerc'])
+        self.check_projection(projs[1],
+                         "EPSG   200 Anguilla 1957 / British West Indies Grid",
+                              ["ellps=clrk80", "k=0.999500",
+                               "lat_0=0.000000000", "lon_0=-62.000000000",
+                               "proj=tmerc", "units=m",
+                               "x_0=400000.000", "y_0=0.000"])
+
+    def test_caching(self):
+        # test whether the projfile cache works
+        projfile, warnings = resource.read_proj_file(self.filename())
+        projfile2, warnings = resource.read_proj_file(self.filename())
+
+        # Both projfiles should be the same object
+        self.assert_(projfile2 is projfile)
+
+        # If we clear the cache we should get a new one.
+        resource.clear_proj_file_cache()
+        projfile3, warnings = resource.read_proj_file(self.filename())
+        self.assert_(projfile3 is not projfile)
+
+
+class TestLoadingProjFileWithEmptyProjectionlist(ProjFileLoadTestCase):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE projectionlist SYSTEM "projfile.dtd">
+<projectionlist>
+</projectionlist>
+'''
+
+    def test(self):
+        projfile, warnings = resource.read_proj_file(self.filename())
+        # no warnings
+        self.assertEquals(warnings, [])
+
+        # There are no projections
+        self.assertEquals(len(projfile.GetProjections()), 0)
+
+
+class TestProjFileWithInvalidParameters(ProjFileLoadTestCase):
+
+    file_contents = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE projectionlist SYSTEM "projfile.dtd">
+<projectionlist>
+    <projection name="Universal Transverse Mercator">
+        <parameter value="proj=utm"/>
+        <parameter value="ellps=clrk66"/>
+        <!-- an invalid zone number to trigger the parameter checking
+             in the proj library -->
+        <parameter value="zone=1000"/>
+    </projection>
+    <projection name="Transverse Mercator">
+        <parameter value="proj=tmerc"/>
+        <parameter value="ellps=clrk66"/>
+        <parameter value="lat_0=90w"/>
+        <parameter value="lon_0=90w"/>
+        <parameter value="k=1"/>
+    </projection>
+</projectionlist>
+'''
+
+    def setUp(self):
+        support.FileLoadTestCase.setUp(self)
+
+    def test(self):
+        """Test reading a proj file with invalid parameters"""
+        projfile, warnings = resource.read_proj_file(self.filename())
+        projs = projfile.GetProjections()
+        self.assertEquals(len(projs), 1)
+        params = projs[0].GetAllParameters()[:]
+        params.sort()
+        self.assertEquals(params, ['ellps=clrk66', 'k=1', 'lat_0=90w',
+                                   'lon_0=90w', 'proj=tmerc'])
+        self.assertEquals(warnings,
+                       ['Error in projection "Universal Transverse Mercator":'
+                        ' invalid UTM zone number'])
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_range.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_range.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_range.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2002, 2003 by Intevation GmbH
+# Authors:
+# Thomas Koester <tkoester at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""
+Unit test for range.py
+"""
+
+__version__ = "$Revision: 1421 $"
+# $Source$
+# $Id: test_range.py 1421 2003-07-15 14:46:55Z bh $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.range import Range, _inf
+
+class RangeTest(unittest.TestCase, support.FloatComparisonMixin):
+
+    def test_equal(self):
+        """test if different ways to create a range yield equal ranges"""
+        range = Range()
+        self.assertEqual(range, Range(''))
+        self.assertEqual(range, Range(']-oo;oo['))
+        self.assertEqual(range, Range((']', -_inf, _inf, '[')))
+        self.assertEqual(range, Range((']', '-oo', 'oo', '[')))
+        range = Range('[0;1]')
+        self.assertEqual(range, Range('[000;1.0]'))
+        self.assertEqual(range, Range(('[', '0', 1.0, ']')))
+        range2 = range
+        self.assertEqual(range, range2)
+        range3 = Range(range)
+        self.assertEqual(range3, range2)
+        range = Range(']0;99]')
+        self.assertEqual(range, Range(']0;99E+00]'))
+        self.assertEqual(range, Range(']0;9.9E+01]'))
+        self.assertEqual(range, Range(']0;990E-01]'))
+        self.assertEqual(range, Range(']0;.99E+02]'))
+        self.assertEqual(range, Range((']', 0, '.99E+02', ']')))
+
+    def test_different(self):
+        """test if different ranges are different"""
+        range = Range('[-1;1]')
+        self.failIfEqual(range, Range(']-1;1]'))
+        self.failIfEqual(range, Range('[-1;1['))
+        self.failIfEqual(range, Range(']-1;1['))
+        self.failIfEqual(range, Range('[0;1]'))
+        self.failIfEqual(range, Range('[-1;0]'))
+
+    def test_contains(self):
+        """test value in range"""
+        range = Range((']', '0', 99, ']'))
+        for value in [-0.1, 0, 99.1]:
+            self.failIf(value in range)
+        for value in [0.1, 9.9, 99]:
+            self.assert_(value in range)
+        range = Range('[-oo;0]')
+        for value in [0.1, float('1e100'), float('1e10000')]:
+            self.failIf(value in range)
+        for value in [0.0, float('-1e100'), float('-1e10000')]:
+            self.assert_(value in range)
+
+    def test_float(self):
+        """test string to float conversion"""
+        range = Range()
+        self.assertFloatEqual(range.float('oo'), _inf)
+        self.assertFloatEqual(range.float('-oo'), -_inf)
+        for value in [-100000000000000000000l, 12345.6789, 0, 0.0, 5.30e20]:
+            self.assertFloatEqual(range.float(str(value)), value)
+
+    def test_short_range(self):
+        """test if range parser handles short ranges"""
+        range = Range('[0;0]')
+        self.failIf(-0.001 in range)
+        self.assert_(0 in range)
+        self.failIf(0.001 in range)
+
+    def test_bad_ranges(self):
+        """test if range parser raises correct exception on bad ranges"""
+        for range in [0, 1.1]:
+            self.assertRaises(TypeError, Range, range)
+        for range in ['x', ']x;9]', ']]0;1]', '[0;1]]', '[0;x]', '0',
+                      '[0]', '[;]', '[0;]', '[;0]', '[1;0]',
+                      ']0;0]', '[0;0[', ']0;0[',
+                      ('[',), ('[', 0), ('[', 0, 1), ('[', 0, ']'),
+                      ('', 0, 1, ']'), ('[', 0, 1, '')]:
+            self.assertRaises(ValueError, Range, range)
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/test/test_save.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_save.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_save.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,645 @@
+# Copyright (c) 2002, 2003, 2004, 2005 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test saving a thuban session as XML
+"""
+
+__version__ = "$Revision: 2688 $"
+# $Source$
+# $Id: test_save.py 2688 2006-06-30 12:27:20Z frank $
+
+import os
+import unittest
+from StringIO import StringIO
+
+import xmlsupport
+import postgissupport
+
+import support
+support.initthuban()
+
+import dbflib
+
+from Thuban import internal_from_unicode
+from Thuban.Lib.fileutil import relative_filename
+from Thuban.Model.save import XMLWriter, save_session, sort_data_stores
+from Thuban.Model.session import Session
+from Thuban.Model.map import Map
+from Thuban.Model.layer import Layer, RasterLayer
+from Thuban.Model.proj import Projection
+from Thuban.Model.table import DBFTable
+from Thuban.Model.transientdb import TransientJoinedTable
+from Thuban.Model.data import DerivedShapeStore, SHAPETYPE_ARC
+
+from Thuban.Model.classification import ClassGroupSingleton, ClassGroupRange, \
+    ClassGroupPattern, ClassGroupProperties
+
+from Thuban.Model.range import Range
+
+from Thuban.Model.postgisdb import PostGISConnection, PostGISShapeStore
+
+
+class XMLWriterTest(unittest.TestCase):
+
+    def testEncode(self):
+        """Test XMLWriter.encode"""
+        writer = XMLWriter()
+        eq = self.assertEquals
+
+        eq(writer.encode("hello world"), "hello world")
+        eq(writer.encode(unicode("hello world")), unicode("hello world"))
+
+        eq(writer.encode(internal_from_unicode(u"\x80\x90\xc2\x100")),
+                         "\xc2\x80\xc2\x90\xc3\x82\x100")
+        eq(writer.encode(u"\x80\x90\xc2\x100"),
+                         "\xc2\x80\xc2\x90\xc3\x82\x100")
+        eq(writer.encode(u"\xFF5E"), "\xc3\xbf5E")
+
+        eq(writer.encode('&"\'<>'), "&amp;&quot;&apos;&lt;&gt;")
+        eq(writer.encode(unicode('&"\'<>')), "&amp;&quot;&apos;&lt;&gt;")
+
+class SaveSessionTest(unittest.TestCase, support.FileTestMixin,
+                      xmlsupport.ValidationTest):
+
+    dtd = "http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
+    thubanids = [((dtd, n), (None, "id")) for n in
+                 ["fileshapesource", "filetable", "jointable",
+                  "derivedshapesource", "dbshapesource", "dbconnection"]]
+    thubanidrefs = [((dtd, n), (None, m)) for n, m in
+                    [("layer", "shapestore"),
+                     ("jointable", "left"),
+                     ("jointable", "right"),
+                     ("derivedshapesource", "table"),
+                     ("derivedshapesource", "shapesource"),
+                     ("dbshapesource", "dbconn")]]
+    del n, m, dtd
+
+    def tearDown(self):
+        """Call self.session.Destroy
+
+        Test cases that create session should bind it to self.session so
+        that it gets destroyed properly
+        """
+        if hasattr(self, "session"):
+            self.session.Destroy()
+            self.session = None
+
+    def compare_xml(self, xml1, xml2):
+        list1 = xmlsupport.sax_eventlist(xml1, ids = self.thubanids,
+                                         idrefs = self.thubanidrefs)
+        list2 = xmlsupport.sax_eventlist(xml2, ids = self.thubanids,
+                                         idrefs = self.thubanidrefs)
+        if list1 != list2:
+            for a, b in zip(list1, list2):
+                if a != b:
+                    self.fail("%r != %r" % (a, b))
+
+
+    def testEmptySession(self):
+        """Save an empty session"""
+        session = Session("empty session")
+        filename = self.temp_file_name("save_emptysession.thuban")
+        save_session(session, filename)
+        session.Destroy()
+
+        file = open(filename)
+        written_contents = file.read()
+        file.close()
+        self.compare_xml(written_contents,
+                         '<?xml version="1.0" encoding="UTF-8"?>\n'
+                         '<!DOCTYPE session SYSTEM "thuban-1.1.dtd">\n'
+                         '<session title="empty session" '
+         'xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">'
+                         '\n</session>\n')
+
+        self.validate_data(written_contents)
+
+    def testSingleLayer(self):
+        """Save a session with a single map with a single layer"""
+        # deliberately put an apersand in the title :)
+        session = Session("single map&layer")
+        proj = Projection(["proj=utm", "zone=27", "ellps=WGS84",
+                           "datum=WGS84", "units=m"],
+                          name = "WGS 84 / UTM zone 27N",
+                          epsg = "32627")
+        map = Map("Test Map", projection = proj)
+        session.AddMap(map)
+        # use shapefile from the example data
+        shpfile = os.path.join(os.path.dirname(__file__),
+                               os.pardir, "Data", "iceland", "political.shp")
+        layer = Layer("My Layer", session.OpenShapefile(shpfile))
+        map.AddLayer(layer)
+
+        filename = self.temp_file_name("save_singlemap.thuban")
+        save_session(session, filename)
+
+        file = open(filename)
+        written_contents = file.read()
+        file.close()
+        expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
+        <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+        <session title="single map&amp;layer"
+           xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
+            <fileshapesource id="D1"
+                filename="../../Data/iceland/political.shp"
+                filetype="shapefile"/>
+            <map title="Test Map">
+                <projection epsg="32627" name="WGS 84 / UTM zone 27N">
+                    <parameter value="proj=utm"/>
+                    <parameter value="zone=27"/>
+                    <parameter value="ellps=WGS84"/>
+                    <parameter value="datum=WGS84"/>
+                    <parameter value="units=m"/>
+                </projection>
+                <layer title="My Layer" shapestore="D1" visible="%s">
+                    <classification>
+                        <clnull label="">
+                            <cldata fill="None" stroke="#000000"
+		    	        stroke_width="1"/>
+                        </clnull>
+                    </classification>
+                </layer>
+            </map>
+        </session>'''
+
+        expected_contents = expected_template % "true"
+
+        self.compare_xml(written_contents, expected_contents)
+
+        self.validate_data(written_contents)
+
+        # Repeat with an invisible layer
+        layer.SetVisible(False)
+        save_session(session, filename)
+
+        file = open(filename)
+        written_contents = file.read()
+        file.close()
+        expected_contents = expected_template % "false"
+        self.compare_xml(written_contents, expected_contents)
+        self.validate_data(written_contents)
+
+        session.Destroy()
+
+    def testLayerProjection(self):
+        """Test saving layers with projections"""
+        # deliberately put an apersand in the title :)
+        session = self.session = Session("single map&layer")
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
+        map = Map("Test Map", projection = proj)
+        session.AddMap(map)
+        # use shapefile from the example data
+        shpfile = os.path.join(os.path.dirname(__file__),
+                               os.pardir, "Data", "iceland", "political.shp")
+        layer = Layer("My Layer", session.OpenShapefile(shpfile))
+        proj = Projection(["proj=lcc", "ellps=clrk66",
+                           "lat_1=0", "lat_2=20"],
+                          "Layer Projection")
+        layer.SetProjection(proj)
+        map.AddLayer(layer)
+
+        filename = self.temp_file_name("save_layerproj.thuban")
+        save_session(session, filename)
+
+        file = open(filename)
+        written_contents = file.read()
+        file.close()
+        expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+        <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+        <session title="single map&amp;layer"
+           xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
+            <fileshapesource id="D1"
+                filename="../../Data/iceland/political.shp"
+                filetype="shapefile"/>
+            <map title="Test Map">
+                <projection name="Unknown">
+                    <parameter value="zone=26"/>
+                    <parameter value="proj=utm"/>
+                    <parameter value="ellps=clrk66"/>
+                </projection>
+                <layer title="My Layer" shapestore="D1" visible="true">
+                    <projection name="Layer Projection">
+                        <parameter value="proj=lcc"/>
+                        <parameter value="ellps=clrk66"/>
+                        <parameter value="lat_1=0"/>
+                        <parameter value="lat_2=20"/>
+                    </projection>
+                    <classification>
+                        <clnull label="">
+                            <cldata fill="None" stroke="#000000"
+		    	        stroke_width="1"/>
+                        </clnull>
+                    </classification>
+                </layer>
+            </map>
+        </session>'''
+        #print written_contents
+        #print "********************************************"
+        #print expected_contents
+        self.compare_xml(written_contents, expected_contents)
+
+        self.validate_data(written_contents)
+
+    def testRasterLayer(self):
+
+        MASK_NONE = RasterLayer.MASK_NONE
+        MASK_BIT = RasterLayer.MASK_BIT
+        MASK_ALPHA = RasterLayer.MASK_ALPHA
+
+        for opacity, masktype, opname, maskname in \
+            [(1,  MASK_BIT,   '', ''),
+             (.2, MASK_BIT,   'opacity="0.2"', ''),
+             (1,  MASK_ALPHA, '',              'masktype="alpha"'),
+             (.5, MASK_ALPHA, 'opacity="0.5"', 'masktype="alpha"'),
+             (1,  MASK_NONE,  '',              'masktype="none"'),
+             (0,  MASK_NONE,  'opacity="0"',   'masktype="none"') ]:
+
+
+            # deliberately put an apersand in the title :)
+            session = Session("single map&layer")
+            map = Map("Test Map")
+            session.AddMap(map)
+            # use shapefile from the example data
+            imgfile = os.path.join(os.path.dirname(__file__),
+                                   os.pardir, "Data", "iceland", "island.tif")
+            layer = RasterLayer("My RasterLayer", imgfile)
+
+            layer.SetOpacity(opacity)
+            layer.SetMaskType(masktype)
+
+            map.AddLayer(layer)
+
+            filename = self.temp_file_name("%s.thuban" % self.id())
+            save_session(session, filename)
+            session.Destroy()
+
+            file = open(filename)
+            written_contents = file.read()
+            file.close()
+            expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+            <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+            <session title="single map&amp;layer"
+               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
+                <map title="Test Map">
+                    <rasterlayer title="My RasterLayer"
+                            filename="../../Data/iceland/island.tif"
+                            visible="true" %s %s>
+                    </rasterlayer>
+                </map>
+            </session>''' % (opname, maskname)
+            #print written_contents
+            #print "********************************************"
+            #print expected_contents
+            self.compare_xml(written_contents, expected_contents)
+
+            self.validate_data(written_contents)
+
+    def testClassifiedLayer(self):
+        """Save a session with a single map with classifications"""
+        # deliberately put an apersand in the title :)
+        session = Session("Map with Classifications")
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
+        map = Map("Test Map", projection = proj)
+        session.AddMap(map)
+        # use shapefile from the example data
+        shpfile = os.path.join(os.path.dirname(__file__),
+                               os.pardir, "Data", "iceland", "political.shp")
+        layer = Layer("My Layer", session.OpenShapefile(shpfile))
+        map.AddLayer(layer)
+        layer2 = Layer("My Layer", layer.ShapeStore())
+        map.AddLayer(layer2)
+
+        clazz = layer.GetClassification()
+
+        layer.SetClassificationColumn("AREA")
+
+        clazz.AppendGroup(ClassGroupSingleton(42, ClassGroupProperties(),
+                                              "single"))
+        clazz.AppendGroup(ClassGroupSingleton("text", ClassGroupProperties(),
+                                              "single-text"))
+
+        clazz.AppendGroup(ClassGroupRange((0, 42),
+                                           ClassGroupProperties(),
+                                           "range"))
+
+        range = ClassGroupRange(Range("[0;42]"))
+        range.SetProperties(ClassGroupProperties())
+        range.SetLabel("new-range")
+        clazz.AppendGroup(range)
+
+
+        clazz = layer2.GetClassification()
+        layer2.SetClassificationColumn("POPYCOUN")
+
+        # Classification with Latin 1 text
+        clazz.AppendGroup(ClassGroupSingleton(
+            internal_from_unicode(u'\xe4\xf6\xfc'), # ae, oe, ue
+            ClassGroupProperties(),
+            internal_from_unicode(u'\xdcml\xe4uts'))) # Uemlaeuts
+
+        # Pattern
+        clazz.AppendGroup(ClassGroupPattern("BUI", ClassGroupProperties(),
+                                            "pattern")) 
+
+        filename = self.temp_file_name("%s.thuban" % self.id())
+        save_session(session, filename)
+
+        file = open(filename)
+        written_contents = file.read()
+        file.close()
+        expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+        <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+        <session title="Map with Classifications"
+           xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
+            <fileshapesource id="D1"
+                filename="../../Data/iceland/political.shp"
+                filetype="shapefile"/>
+            <map title="Test Map">
+                <projection name="Unknown">
+                    <parameter value="zone=26"/>
+                    <parameter value="proj=utm"/>
+                    <parameter value="ellps=clrk66"/>
+                </projection>
+                <layer title="My Layer" shapestore="D1" visible="true">
+                    <classification field="AREA" field_type="double">
+                        <clnull label="">
+                            <cldata fill="None" stroke="#000000" stroke_width="1"/>
+                        </clnull>
+                        <clpoint value="42" label="single">
+                            <cldata fill="None" stroke="#000000" stroke_width="1"/>
+                        </clpoint>
+                        <clpoint value="text" label="single-text">
+                            <cldata fill="None" stroke="#000000" stroke_width="1"/>
+                        </clpoint>
+                        <clrange range="[0;42[" label="range">
+                            <cldata fill="None" stroke="#000000" stroke_width="1"/>
+                        </clrange>
+                        <clrange range="[0;42]" label="new-range">
+                            <cldata fill="None" stroke="#000000" stroke_width="1"/>
+                        </clrange>
+                    </classification>
+                </layer>
+                <layer title="My Layer" shapestore="D1" visible="true">
+                    <classification field="POPYCOUN" field_type="string">
+                        <clnull label="">
+                            <cldata fill="None" stroke="#000000" stroke_width="1"/>
+                        </clnull>
+                        <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
+                             label="\xc3\x9cml\xc3\xa4uts">
+                            <cldata fill="None" stroke="#000000" stroke_width="1"/>
+                        </clpoint>
+                        <clpattern pattern="BUI" label="pattern">
+                            <cldata fill="None" stroke="#000000" stroke_width="1"/>
+                        </clpattern>
+                    </classification>
+                </layer>
+            </map>
+        </session>'''
+
+        #print written_contents
+        #print "********************************************"
+        #print expected_contents
+        self.compare_xml(written_contents, expected_contents)
+
+        self.validate_data(written_contents)
+
+        session.Destroy()
+
+    def test_dbf_table(self):
+        """Test saving a session with a dbf table link"""
+        session = self.session = Session("a DBF Table session")
+        # use shapefile from the example data
+        dbffile = os.path.join(os.path.dirname(__file__),
+                               os.pardir, "Data", "iceland", "political.dbf")
+        table = session.AddTable(DBFTable(dbffile))
+
+        filename = self.temp_file_name("save_singletable.thuban")
+        save_session(session, filename)
+
+        file = open(filename)
+        written_contents = file.read()
+        file.close()
+        expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+        <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+        <session title="a DBF Table session"
+           xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
+            <filetable id="D1" filename="../../Data/iceland/political.dbf"
+                filetype="DBF" title="political"/>
+        </session>'''
+
+        self.compare_xml(written_contents, expected_contents)
+        self.validate_data(written_contents)
+
+    def test_joined_table(self):
+        """Test saving a session with joined table"""
+        # Create a simple table to use in the join
+        dbffile = self.temp_file_name("save_joinedtable.dbf")
+        dbf = dbflib.create(dbffile)
+        dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
+        dbf.add_field("TEXT", dbflib.FTString, 10, 0)
+        dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
+        dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
+        dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
+        dbf.close()
+
+        # Create the session and a map
+        session = Session("A Joined Table session")
+        try:
+            map = Map("Test Map")
+            session.AddMap(map)
+
+            # Add the dbf file to the session
+            dbftable = session.AddTable(DBFTable(dbffile))
+
+            # Create a layer with the shapefile to use in the join
+            shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
+                                   os.pardir, "Data", "iceland",
+                                   "roads-line.shp")
+            layer = Layer("My Layer", session.OpenShapefile(shpfile))
+            map.AddLayer(layer)
+
+            # Do the join
+            store = layer.ShapeStore()
+            #for col in store.Table().Columns():
+            #    print col.name
+            joined = TransientJoinedTable(session.TransientDB(),
+                                          store.Table(), "RDLNTYPE",
+                                          dbftable, "RDTYPE",
+                                          outer_join = True)
+            store = session.AddShapeStore(DerivedShapeStore(store, joined))
+            layer.SetShapeStore(store)
+
+            # Save the session
+            filename = self.temp_file_name("save_joinedtable.thuban")
+            save_session(session, filename)
+
+            # Read it back and compare
+            file = open(filename)
+            written_contents = file.read()
+            file.close()
+            expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
+            <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+            <session title="A Joined Table session"
+             xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
+                <fileshapesource filename="../../Data/iceland/roads-line.shp"
+                                 filetype="shapefile" id="D142197204"/>
+                <filetable filename="save_joinedtable.dbf"
+                           title="save_joinedtable"
+                           filetype="DBF" id="D141881756"/>
+                <jointable id="D142180284"
+                           title="Join of roads-line and save_joinedtable"
+                           leftcolumn="RDLNTYPE" left="D142197204"
+                           rightcolumn="RDTYPE" right="D141881756"
+                           jointype="LEFT OUTER" />
+                <derivedshapesource id="D141915644"
+                                    table="D142180284"
+                                    shapesource="D142197204"/>
+                <map title="Test Map">
+                    <layer title="My Layer"
+                           shapestore="D141915644" visible="true">
+                        <classification>
+                            <clnull label="">
+                                <cldata fill="None" stroke="#000000"
+				        stroke_width="1"/>
+                            </clnull>
+                        </classification>
+                    </layer>
+                </map>
+            </session>'''
+
+            self.compare_xml(written_contents, expected_contents)
+            self.validate_data(written_contents)
+        finally:
+            session.Destroy()
+            session = None
+
+
+    def test_save_postgis(self):
+        """Test saving a session with a postgis connection"""
+
+        class NonConnection(PostGISConnection):
+            """connection class that doesn't actually connect """
+            def connect(self):
+                pass
+
+        class NonConnectionStore(PostGISShapeStore):
+            """Shapestore that doesn't try to access the server"""
+            def _fetch_table_information(self):
+                # pretend that we've found a geometry column
+                self.geometry_column = "the_geom"
+		# pretend this is a ARC shape type.
+		self.shape_type = SHAPETYPE_ARC
+            def IDColumn(self):
+                """Return an object with a name attribute with value 'gid'"""
+                class dummycol:
+                    name = "gid"
+                return dummycol
+
+        session = Session("A PostGIS Session")
+        try:
+            dbconn = NonConnection(dbname="plugh", host="xyzzy", port="42",
+                                   user="grue")
+            session.AddDBConnection(dbconn)
+            map = Map("Test Map")
+            session.AddMap(map)
+            store = NonConnectionStore(dbconn, "roads")
+            session.AddShapeStore(store)
+            layer = Layer("Roads to Nowhere", store)
+            map.AddLayer(layer)
+
+            # Save the session
+            filename = self.temp_file_name(self.id() + ".thuban")
+            save_session(session, filename)
+
+            # Read it back and compare
+            file = open(filename)
+            written = file.read()
+            file.close()
+            expected = '''<?xml version="1.0" encoding="UTF-8"?>
+            <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
+            <session title="A PostGIS Session"
+             xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
+                <dbconnection id="DB"
+                              dbtype="postgis" dbname="plugh"
+                              host="xyzzy" port="42"
+                              user="grue"/>
+                <dbshapesource id="roads" dbconn="DB" tablename="roads"
+                               id_column="gid" geometry_column="the_geom"/>
+                <map title="Test Map">
+                    <layer title="Roads to Nowhere"
+                           shapestore="roads" visible="true">
+                        <classification>
+                            <clnull label="">
+                                <cldata fill="None" stroke="#000000"
+		    	            stroke_width="1"/>
+                            </clnull>
+                        </classification>
+                    </layer>
+                </map>
+            </session>'''
+            self.compare_xml(written, expected)
+            self.validate_data(written)
+        finally:
+            session.Destroy()
+
+
+class MockDataStore:
+
+    """A very simple data store that only has dependencies"""
+
+    def __init__(self, name, *dependencies):
+        self.name = name
+        self.dependencies = dependencies
+
+    def __repr__(self):
+        return self.name
+
+    def Dependencies(self):
+        return self.dependencies
+
+
+class TestStoreSort(unittest.TestCase):
+
+    def check_sort(self, containers, sorted):
+        """Check whether the list of data containers is sorted"""
+        # check whether sorted is in the right order
+        seen = {}
+        for container in sorted:
+            self.failIf(id(container) in seen,
+                        "Container %r at least twice in %r" % (container,
+                                                               sorted))
+            for dep in container.Dependencies():
+                self.assert_(id(dep) in seen,
+                             "Dependency %r of %r not yet seen" % (dep,
+                                                                   container))
+            seen[id(container)] = 1
+        # check whether all of containers is in sorted
+        for container in containers:
+            self.assert_(id(container) in seen,
+                         "Container %r in containers but not in sorted")
+        self.assertEquals(len(containers), len(sorted))
+
+    def test_sort_data_stores(self):
+        """Test Thuban.Model.save.sort_data_stores"""
+        d1 = MockDataStore("d1")
+        d2 = MockDataStore("d2")
+        d3 = MockDataStore("d3", d1)
+        d4 = MockDataStore("d4", d1, d3)
+
+        containers = [d4, d1, d2, d3]
+        self.check_sort(containers, sort_data_stores(containers))
+        containers = [d1, d3, d2, d4]
+        self.check_sort(containers, sort_data_stores(containers))
+
+
+
+if __name__ == "__main__":
+    # Fake the __file__ global because it's needed by a test
+    import sys
+    __file__ = sys.argv[0]
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_scalebar.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_scalebar.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_scalebar.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,102 @@
+# Copyright (c) 2002 by Intevation GmbH
+# Authors:
+# Frank Koormann <frank.koormann at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Thuban scalebar calculations
+"""
+
+__version__ = "$Revision: 1674 $"
+# $Source$
+# $Id: test_scalebar.py 1674 2003-08-28 13:07:58Z bh $
+
+import unittest
+import os
+
+import support
+support.initthuban()
+
+from Thuban.Model.scalebar import deriveInterval, roundInterval
+
+class TestScalebar(unittest.TestCase, support.FloatComparisonMixin):
+
+    """Test cases for the Thuban scalebar calculations
+    """
+
+    def test_deriveInterval(self):
+        """Test scalebar.deriveInterval()"""
+
+        # Zero savety
+        interval, unit = deriveInterval(100, 0.0)
+        self.assertEquals(interval, -1)
+        self.assertEquals(unit, '')
+
+        # meters
+        interval, unit = deriveInterval(100, 0.5)
+        self.assertEquals(interval, 200)
+        self.assertEquals(unit, 'm')
+    
+        # kilometer conversion
+        interval, unit = deriveInterval(100, 0.05)
+        self.assertEquals(interval, 2)
+        self.assertEquals(unit, 'km')
+    
+    def test_roundInterval(self):
+        """Test scalebar.roundInterval()"""
+        
+        # 0.0005
+        interval, label = roundInterval(0.000545943795)
+        self.assertFloatEqual(interval, 0.0005)
+        self.assertEquals(label, '0.0005')
+        
+        # 0.005
+        interval, label = roundInterval(0.00545943795)
+        self.assertFloatEqual(interval, 0.005)
+        self.assertEquals(label, '0.005')
+            
+        # 0.05
+        interval, label = roundInterval(0.0545943795)
+        self.assertFloatEqual(interval, 0.05)
+        self.assertEquals(label, '0.05')
+            
+        # 0.5
+        interval, label = roundInterval(0.545943795)
+        self.assertFloatEqual(interval, 0.5)
+        self.assertEquals(label, '0.5')
+            
+        # 5
+        interval, label = roundInterval(5.45943795)
+        self.assertFloatEqual(interval, 5)
+        self.assertEquals(label, '5')
+    
+        # 50
+        interval, label = roundInterval(54.5943795)
+        self.assertFloatEqual(interval, 50)
+        self.assertEquals(label, '50')
+    
+        # 500
+        interval, label = roundInterval(545.943795)
+        self.assertFloatEqual(interval, 500)
+        self.assertEquals(label, '500')
+    
+        # 5000
+        interval, label = roundInterval(5459.43795)
+        self.assertFloatEqual(interval, 5000)
+        self.assertEquals(label, '5000')
+    
+        # 50000
+        interval, label = roundInterval(54594.3795)
+        self.assertFloatEqual(interval, 50000)
+        self.assertEquals(label, '50000')
+    
+        # 500000
+        interval, label = roundInterval(545943.795)
+        self.assertFloatEqual(interval, -1)
+        self.assertEquals(label, '')
+
+if __name__ == "__main__":
+    unittest.main()
+

Added: packages/thuban/branches/upstream/current/test/test_selection.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_selection.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_selection.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,304 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""
+Test cases for Thuban.UI.selection
+"""
+
+__version__ = "$Revision: 723 $"
+# $Source$
+# $Id: test_selection.py 723 2003-04-24 15:31:53Z bh $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.session import Session
+from Thuban.Model.map import Map
+from Thuban.Model.layer import Layer
+from Thuban.UI.selection import Selection
+from Thuban.UI.messages import LAYER_SELECTED, SHAPES_SELECTED
+
+
+class TestSelection(unittest.TestCase, support.SubscriberMixin):
+
+    def setUp(self):
+        """Instantiate a selection.
+
+        Test cases implemented in this class can access the selection as
+        self.selection.
+
+        Also, subscribe self.subscribe_with_params to some of the
+        selection's messages.
+
+        Finally, create a list self.to_destroy with objects to be
+        destroyes by calling their destroy method in tearDown() for
+        objects created in test cases that need to be destroyed.
+        """
+        self.clear_messages()
+        self.selection = Selection()
+        for channel in (LAYER_SELECTED, SHAPES_SELECTED):
+            self.selection.Subscribe(channel, self.subscribe_with_params,
+                                     channel)
+        self.to_destroy = [self.selection]
+
+    def tearDown(self):
+        """Destroy all objects in self.to_destroy and clear the message list"""
+        for obj in self.to_destroy:
+            obj.Destroy()
+        self.to_destroy = None
+        self.session = None
+        self.selection = None
+        self.clear_messages()
+
+    def get_layer(self):
+        """Return a layer to have something to test with.
+
+        Also, instantiate self.session if not done already. The layer
+        (and the session when it is created) are added to
+        self.to_destroy so that they are properly destroyed at the end
+        of the test.
+
+        The layer should not be added to a map in the session to avoid a
+        situation where its destroy method is called twice. This
+        situation should not arise in the selection tests.
+        """
+        if not hasattr(self, "session"):
+            self.session = Session("Test Session for %s" % self.__class__)
+            self.to_destroy.append(self.session)
+        filename = os.path.join("..", "Data", "iceland", "roads-line.shp")
+        layer = Layer("Selection Test Layer",
+                      self.session.OpenShapefile(filename))
+        self.to_destroy.append(layer)
+        return layer
+
+    def test_instatiation(self):
+        """Test initial state of the selection"""
+        self.assertEquals(self.selection.SelectedLayer(), None)
+        self.assertEquals(self.selection.SelectedShapes(), [])
+        self.failIf(self.selection.HasSelectedLayer())
+
+    #
+    #   SelectLayer Tests
+    #
+
+    def test_select_layer_without_current_selection(self):
+        """Test Selection.SelectLayer() without current selection"""
+        layer = self.get_layer()
+
+        self.selection.SelectLayer(layer)
+        # After selecting a layer, no shapes are selected
+        self.assertEquals(self.selection.SelectedLayer(), layer)
+        self.failUnless(self.selection.HasSelectedLayer())
+        self.assertEquals(self.selection.SelectedShapes(), [])
+        # Since no shape was selected, only a LAYER_SELECTED message
+        # should have been issued.
+        self.check_messages([(layer, LAYER_SELECTED)])
+
+    def test_select_currently_selected_layer(self):
+        """Test Selection.SelectLayer(<currently selected layer>)"""
+        layer = self.get_layer()
+
+        self.selection.SelectLayer(layer)
+        self.clear_messages()
+        self.selection.SelectLayer(layer)
+
+        # After selecting a layer, no shapes are selected
+        self.assertEquals(self.selection.SelectedLayer(), layer)
+        self.failUnless(self.selection.HasSelectedLayer())
+        self.assertEquals(self.selection.SelectedShapes(), [])
+        # Since nothing has changed, really, no messages should have
+        # been issued
+        self.check_messages([])
+
+    def test_select_layer_with_previous_selection(self):
+        """Test Selection.SelectLayer() with previous selection"""
+        self.selection.SelectShapes(self.get_layer(), [0])
+        self.clear_messages()
+
+        layer = self.get_layer()
+        self.selection.SelectLayer(layer)
+
+        # After selecting a layer, no shapes are selected
+        self.assertEquals(self.selection.SelectedLayer(), layer)
+        self.failUnless(self.selection.HasSelectedLayer())
+        self.assertEquals(self.selection.SelectedShapes(), [])
+        # Since a shape and a layer was selected, a LAYER_SELECTED and a
+        # SHAPES_SELECTED message should have been issued.
+        self.check_messages([(layer, LAYER_SELECTED),
+                             (layer, [], SHAPES_SELECTED)])
+
+    def test_select_layer_with_None(self):
+        """Test Selection.SelectLayer(None)
+
+        Calling SelectLayer with None should deselect it.
+        """
+        self.selection.SelectShapes(self.get_layer(), [0])
+        self.clear_messages()
+        self.selection.SelectLayer(None)
+
+        # After selecting a layer, no shapes are selected
+        self.assertEquals(self.selection.SelectedLayer(), None)
+        self.failIf(self.selection.HasSelectedLayer())
+        self.assertEquals(self.selection.SelectedShapes(), [])
+        # Since no shape was selected, only a LAYER_SELECTED message
+        # should have been issued.
+        self.check_messages([(None, LAYER_SELECTED),
+                             (None, [], SHAPES_SELECTED)])
+
+    #
+    #   SelectShapes Tests
+    #
+
+    def test_select_new_layer_and_new_shape(self):
+        """Test Selection.SelectShapes(<new layer>, <new shapes>)"""
+        layer = self.get_layer()
+
+        self.selection.SelectShapes(layer, [0, 3, 1])
+
+        self.assertEquals(self.selection.SelectedLayer(), layer)
+        self.failUnless(self.selection.HasSelectedLayer())
+        self.assertEquals(self.selection.SelectedShapes(), [0, 1, 3])
+        self.check_messages([(layer, LAYER_SELECTED),
+                             (layer, [0, 1, 3], SHAPES_SELECTED)])
+
+    def test_select_old_layer_and_old_shape(self):
+        """Test Selection.SelectShape(<old layer>, <old shapes>)"""
+        layer = self.get_layer()
+
+        self.selection.SelectShapes(layer, [0, 10, 2])
+        self.clear_messages()
+        # Deliberate use a different order of the shape ids to check
+        # whether they're still considered equal
+        self.selection.SelectShapes(layer, [2, 0, 10])
+
+        # Selecting an already selected layer and shapes should not
+        # result in any messages but still have the right layer and
+        # shapes selected
+        self.assertEquals(self.selection.SelectedLayer(), layer)
+        self.failUnless(self.selection.HasSelectedLayer())
+        self.assertEquals(self.selection.SelectedShapes(), [0, 2, 10])
+        self.check_messages([])
+
+    def test_select_old_layer_and_new_shape(self):
+        """Test Selection.SelectShapes(<old layer>, <new shape>)"""
+        layer = self.get_layer()
+
+        self.selection.SelectShapes(layer, [0])
+        self.clear_messages()
+        self.selection.SelectShapes(layer, [1])
+
+        # Selecting a different shape in the already selected layer
+        # should only produce a SHAPES_SELECTED message
+        # After selecting a shape, both a shape and a layer are selected
+        self.assertEquals(self.selection.SelectedLayer(), layer)
+        self.failUnless(self.selection.HasSelectedLayer())
+        self.assertEquals(self.selection.SelectedShapes(), [1])
+        self.check_messages([(layer, [1], SHAPES_SELECTED)])
+
+    #
+    #   Adding Shapes Tests
+    #
+
+    def test_add_shapes_new_layer_new_shapes(self):
+        """Test Selection.SelectShapes(<same layer>, <new shapes>, add = 1)"""
+        layer = self.get_layer()
+
+        self.selection.SelectShapes(layer, [10, 7], add = 1)
+
+        self.assertEquals(self.selection.SelectedLayer(), layer)
+        self.failUnless(self.selection.HasSelectedLayer())
+        # The list of selected shapes will be sorted in ascending order
+        self.assertEquals(self.selection.SelectedShapes(), [7, 10])
+        self.check_messages([(layer, LAYER_SELECTED),
+                             (layer, [7, 10], SHAPES_SELECTED)])
+
+    def test_add_shapes_same_layer_new_shapes(self):
+        """Test Selection.SelectShapes(<same layer>, <new shapes>, add = 1)"""
+        layer = self.get_layer()
+
+        self.selection.SelectShapes(layer, [0, 6, 5])
+        self.clear_messages()
+
+        self.selection.SelectShapes(layer, [10, 7], add = 1)
+
+        self.assertEquals(self.selection.SelectedLayer(), layer)
+        self.failUnless(self.selection.HasSelectedLayer())
+        # The list of selected shapes will be sorted in ascending order
+        self.assertEquals(self.selection.SelectedShapes(), [0, 5, 6, 7, 10])
+        self.check_messages([(layer, [0, 5, 6, 7, 10], SHAPES_SELECTED)])
+
+    def test_add_shapes_same_layer_already_selected_shapes(self):
+        """Test Selection.SelectShapes(<same layer>, <some old shapes>, add=1)
+        """
+        layer = self.get_layer()
+
+        self.selection.SelectShapes(layer, [0, 6, 5])
+        self.clear_messages()
+
+        self.selection.SelectShapes(layer, [6, 0], add = 1)
+
+        self.assertEquals(self.selection.SelectedLayer(), layer)
+        self.failUnless(self.selection.HasSelectedLayer())
+        # The list of selected shapes will be sorted in ascending order
+        self.assertEquals(self.selection.SelectedShapes(), [0, 5, 6])
+        self.check_messages([])
+
+    #
+    #   ClearSelection Tests
+    #
+
+    def test_clear_selection(self):
+        """Test Selection.ClearSelection() when nothing is selected"""
+        self.selection.ClearSelection()
+
+        # After clearing the selection nothing is selected
+        self.assertEquals(self.selection.SelectedLayer(), None)
+        self.failIf(self.selection.HasSelectedLayer())
+        self.assertEquals(self.selection.SelectedShapes(), [])
+        # No messages should have been sent because the selection
+        # doesn't have changed due to the ClearSelection()
+        self.check_messages([])
+
+    def test_clear_selection_with_selected_layer(self):
+        """Test Selection.ClearSelection() when a layer is selected"""
+        self.selection.ClearSelection()
+
+        self.selection.SelectLayer(self.get_layer())
+        self.clear_messages()
+        self.selection.ClearSelection()
+
+        # After clearing the selection nothing is selected
+        self.assertEquals(self.selection.SelectedLayer(), None)
+        self.failIf(self.selection.HasSelectedLayer())
+        self.assertEquals(self.selection.SelectedShapes(), [])
+        # No messages should have been sent because the selection
+        # doesn't have changed due to the ClearSelection()
+        self.check_messages([(None, LAYER_SELECTED)])
+
+    def test_clear_selection_with_selected_shape(self):
+        """Test Selection.ClearSelection() when a layer is selected"""
+        self.selection.ClearSelection()
+
+        self.selection.SelectShapes(self.get_layer(), [0])
+        self.clear_messages()
+        self.selection.ClearSelection()
+
+        # After clearing the selection nothing is selected
+        self.assertEquals(self.selection.SelectedLayer(), None)
+        self.failIf(self.selection.HasSelectedLayer())
+        self.assertEquals(self.selection.SelectedShapes(), [])
+        # No messages should have been sent because the selection
+        # doesn't have changed due to the ClearSelection()
+        self.check_messages([(None, LAYER_SELECTED),
+                             (None, [], SHAPES_SELECTED)])
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_session.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_session.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_session.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,412 @@
+# Copyright (c) 2002, 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Session class
+"""
+
+__version__ = "$Revision: 1676 $"
+# $Source$
+# $Id: test_session.py 1676 2003-08-28 13:14:44Z bh $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.messages import CHANGED, MAPS_CHANGED, FILENAME_CHANGED, \
+     MAP_PROJECTION_CHANGED, MAP_LAYERS_CHANGED, \
+     LAYER_VISIBILITY_CHANGED, LAYER_CHANGED, TABLE_REMOVED
+from Thuban.Model.session import Session
+from Thuban.Model.map import Map
+from Thuban.Model.layer import Layer
+from Thuban.Model.proj import Projection
+from Thuban.Model.color import Color
+from Thuban.Model.table import MemoryTable, FIELDTYPE_STRING, \
+                               FIELDTYPE_INT, FIELDTYPE_DOUBLE
+from Thuban.Model.data import DerivedShapeStore
+from Thuban.Model.transientdb import TransientJoinedTable
+
+class TestSessionSimple(unittest.TestCase):
+
+    """Very simple test cases for Session"""
+
+    def setUp(self):
+        """Initialize self.session to None"""
+        self.session = None
+
+    def tearDown(self):
+        """Call self.session.Destroy() and reset self.session to None"""
+        self.session.Destroy()
+        self.session = None
+
+    def test_initial_state(self):
+        """Test Session's initial state"""
+        session = self.session = Session("Test Session")
+        self.assertEquals(session.Title(), "Test Session")
+        self.assertEquals(session.Maps(), [])
+        self.assertEquals(session.Tables(), [])
+        self.assertEquals(session.ShapeStores(), [])
+        self.assertEquals(session.filename, None)
+        self.failIf(session.HasMaps())
+        self.failIf(session.WasModified())
+
+    def test_add_table(self):
+        """Test Session.AddTable()"""
+        session = self.session = Session("Test Session")
+        memtable = MemoryTable([("type", FIELDTYPE_STRING),
+                                ("value", FIELDTYPE_DOUBLE),
+                                ("code", FIELDTYPE_INT)],
+                               [("OTHER/UNKNOWN", -1.5, 11),
+                                ("RUINS", 0.0, 1),
+                                ("FARM", 3.141, 2),
+                                ("BUILDING", 2.5, 3),
+                                ("HUT", 1e6, 4),
+                                ("LIGHTHOUSE", -0.01, 5)])
+
+        # The session should be unmodified before the AddTable call and
+        # modified afterwards and of course the table should show up in
+        # Tables
+        self.failIf(session.WasModified())
+        table = session.AddTable(memtable)
+        self.assertEquals(session.Tables(), [table])
+        self.failUnless(session.WasModified())
+
+    def test_open_table_file(self):
+        """Test Session.OpenTableFile()"""
+        session = self.session = Session("Test Session")
+        filename = os.path.join("..", "Data", "iceland",
+                                "roads-line.dbf")
+        table = session.OpenTableFile(filename)
+        self.assertEquals(session.Tables(), [table])
+
+    def test_open_shapefile(self):
+        """Test Session.OpenShapefile()"""
+        session = self.session = Session("Test Session")
+        filename = os.path.join("..", "Data", "iceland",
+                                "roads-line.shp")
+        store = session.OpenShapefile(filename)
+        self.assertEquals(store.FileName(), os.path.abspath(filename))
+        # The filetype of a shapefile is "shapefile"
+        self.assertEquals(store.FileType(), "shapefile")
+        # The shapestore itself depends on nothing else
+        self.assertEquals(store.Dependencies(), ())
+        # The shapestore's table depends on the shapestore
+        self.assertEquals(store.Table().Dependencies(), (store,))
+
+        self.assertEquals(session.Tables(), [store.Table()])
+
+    def test_add_shapestore(self):
+        """Test Session.AddShapeStore()"""
+        session = self.session = Session("Test Session")
+        filename = os.path.join("..", "Data", "iceland",
+                                "roads-line.shp")
+        try:
+            store = session.OpenShapefile(filename)
+            derived = DerivedShapeStore(store, store.Table())
+            session.AddShapeStore(derived)
+            self.assertEquals(session.ShapeStores(), [store, derived])
+        finally:
+            store = derived = None
+
+
+    def test_unreferenced_tables(self):
+        """Test Session.UnreferencedTables()"""
+        session = self.session = Session("Test Session")
+        filename = os.path.join("..", "Data", "iceland",
+                                "roads-line.shp")
+        try:
+            store = session.OpenShapefile(filename)
+            filename = os.path.join("..", "Data", "iceland",
+                                    "roads-line.dbf")
+            table = session.OpenTableFile(filename)
+            self.assertEquals(session.Tables(), [table, store.Table()])
+            # The store's table is reference by the store, so the only
+            # unreferenced table is the roads-line table
+            self.assertEquals(session.UnreferencedTables(), [table])
+        finally:
+            store = table = None
+
+
+class UnreferencedTablesTests(unittest.TestCase):
+
+    """Test cases for the session.UnreferencedTables() method"""
+
+    def setUp(self):
+        """Create a session with a few test tables"""
+        self.session = Session("Test Session")
+        memtable = MemoryTable([("type", FIELDTYPE_STRING),
+                                ("value", FIELDTYPE_DOUBLE),
+                                ("code", FIELDTYPE_INT)],
+                               [("OTHER/UNKNOWN", -1.5, 11),
+                                ("RUINS", 0.0, 1),
+                                ("FARM", 3.141, 2),
+                                ("BUILDING", 2.5, 3),
+                                ("HUT", 1e6, 4),
+                                ("LIGHTHOUSE", -0.01, 5)])
+        self.memtable = self.session.AddTable(memtable)
+        filename = os.path.join("..", "Data", "iceland",
+                                "roads-line.dbf")
+        self.roads_line = self.session.OpenTableFile(filename)
+        filename = os.path.join("..", "Data", "iceland",
+                                "cultural_landmark-point.dbf")
+        self.landmarks = self.session.OpenTableFile(filename)
+
+    def tearDown(self):
+        """Clear the session and layers"""
+        self.memtable = self.roads_line = self.landmarks = None
+        self.session.Destroy()
+        self.session = None
+
+    def test_unreferenced_tables(self):
+        """Test Session.UnreferencedTables()"""
+        self.assertEquals(self.session.UnreferencedTables(),
+                          [self.memtable, self.roads_line, self.landmarks])
+
+    def test_unreferenced_tables_with_joins(self):
+        """Test Session.UnreferencedTables() with joins"""
+        joined = TransientJoinedTable(self.session.TransientDB(),
+                                      self.landmarks, "CLPTLABEL",
+                                      self.memtable, "type", outer_join = True)
+        try:
+            joined = self.session.AddTable(joined)
+            # After the join, landmarks and memtable are referenced by
+            # joined which in turn is referenced by nothing
+            self.assertEquals(self.session.UnreferencedTables(),
+                              [self.roads_line, joined])
+            # Creating a DerivedShapeStore that references the joined table
+            # will remove it from the list of unreferenced tables,
+            store = self.session.OpenShapefile(
+                os.path.join("..", "Data", "iceland",
+                             "cultural_landmark-point.dbf"))
+            derived = DerivedShapeStore(store, joined)
+            self.session.AddShapeStore(derived)
+            self.assertEquals(self.session.UnreferencedTables(),
+                              [self.roads_line])
+        finally:
+            joined = derived = store = None
+
+class TestSessionBase(unittest.TestCase, support.SubscriberMixin):
+
+    """Base class for Session test cases that test the messages"""
+
+    def setUp(self):
+        """
+        Clear the message list, create a session and subscribe to its messages
+
+        Bind the session to self.session.
+        """
+        self.clear_messages()
+
+        # Create a Session and subscribe to all interesting channels.
+        self.session = Session("Test Session")
+        for channel in (CHANGED,
+                        MAPS_CHANGED,
+                        FILENAME_CHANGED,
+                        MAP_PROJECTION_CHANGED,
+                        MAP_LAYERS_CHANGED,
+                        LAYER_VISIBILITY_CHANGED,
+                        LAYER_CHANGED,
+                        TABLE_REMOVED):
+            self.session.Subscribe(channel,
+                                   self.subscribe_with_params, channel)
+
+    def tearDown(self):
+        """Destroy self.session and clear the message list"""
+        self.session.Destroy()
+        self.session = None
+        self.clear_messages()
+
+
+class TestSessionMessages(TestSessionBase):
+
+    """Simple Session test cases that test messges"""
+
+    def test_add_map(self):
+        """Test Session.AddMap"""
+        self.failIf(self.session.WasModified())
+        map = Map("Some Map")
+        self.session.AddMap(map)
+        self.assert_(self.session.HasMaps())
+        self.assert_(self.session.WasModified())
+        self.assertEquals(self.session.Maps(), [map])
+        self.check_messages([(MAPS_CHANGED,),
+                             (self.session, CHANGED)])
+
+    def test_set_filename(self):
+        """Test Session.SetFilename"""
+        self.session.SetFilename("session_set_filename_test")
+        self.session.filename = "session_set_filename_test"
+        self.check_messages([(FILENAME_CHANGED,),
+                             (self.session, CHANGED)])
+
+    def test_remove_table(self):
+        """Test Session.RemoveTable()"""
+        memtable = MemoryTable([("type", FIELDTYPE_STRING),
+                                ("value", FIELDTYPE_DOUBLE),
+                                ("code", FIELDTYPE_INT)],
+                               [("OTHER/UNKNOWN", -1.5, 11),
+                                ("RUINS", 0.0, 1),
+                                ("FARM", 3.141, 2),
+                                ("BUILDING", 2.5, 3),
+                                ("HUT", 1e6, 4),
+                                ("LIGHTHOUSE", -0.01, 5)])
+        table = self.session.AddTable(memtable)
+        self.assertEquals(self.session.Tables(), [table])
+        self.clear_messages()
+        self.session.RemoveTable(table)
+        self.check_messages([(table, TABLE_REMOVED),
+                             (self.session, CHANGED)])
+        self.assertEquals(self.session.Tables(), [])
+        self.assertRaises(ValueError, self.session.RemoveTable, table)
+
+
+class TestSessionWithContent(TestSessionBase):
+
+    """Session test cases that start with a filled session."""
+
+    def setUp(self):
+        """Extend the inherited method to add a non-empty map to self.session
+        """
+        TestSessionBase.setUp(self)
+        open_shp = self.session.OpenShapefile
+        self.arc_layer = Layer("Roads",
+                               open_shp(os.path.join("..", "Data", "iceland",
+                                                     "roads-line.shp")))
+        self.poly_layer = Layer("Political",
+                                open_shp(os.path.join("..", "Data", "iceland",
+                                                      "political.shp")))
+        self.map = Map("A Map")
+        self.map.AddLayer(self.arc_layer)
+        self.map.AddLayer(self.poly_layer)
+        self.session.AddMap(self.map)
+        self.session.UnsetModified()
+        self.clear_messages()
+
+    def tearDown(self):
+        TestSessionBase.tearDown(self)
+        self.arc_layer = self.poly_layer = None
+
+    def test_remove_map(self):
+        """Test Session.RemoveMap"""
+        self.session.RemoveMap(self.map)
+        self.assert_(self.session.WasModified())
+        self.failIf(self.session.HasMaps())
+        self.check_messages([(MAPS_CHANGED,),
+                             (self.session, CHANGED)])
+
+    def test_tree_info(self):
+        """Test Session.TreeInfo"""
+        self.assertEquals(self.session.TreeInfo(),
+                          ('Session: Test Session',
+                           ['Filename:',
+                            'Unmodified',
+                            self.map]))
+
+    def test_forward_map_projection(self):
+        """Test Session forwarding of Map.SetProjection messages"""
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
+        self.map.SetProjection(proj)
+        self.check_messages([(self.map, MAP_PROJECTION_CHANGED),
+                             (self.session, CHANGED)])
+        self.assert_(self.session.WasModified())
+
+    def test_forward_map_projection(self):
+        """Test Session forwarding of Map.SetProjection messages"""
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
+        self.map.SetProjection(proj)
+        self.assert_(self.session.WasModified())
+        self.check_messages([(self.map, None, MAP_PROJECTION_CHANGED),
+                             (self.session, CHANGED)])
+
+    def test_forwarding_fill(self):
+        """Test Session's forwarding of Layer.SetFill messages"""
+        self.poly_layer.GetClassification().SetDefaultFill(Color(0.0, 0.5, 1.0))
+        self.assert_(self.session.WasModified())
+        self.check_messages([(self.poly_layer, LAYER_CHANGED),
+                             (self.session, CHANGED)])
+
+    def test_forwarding_stroke(self):
+        """Test Session's forwarding of Layer.SetStroke messages"""
+        self.poly_layer.GetClassification().\
+            SetDefaultLineColor(Color(0.0, 0.5, 1.0))
+        self.assert_(self.session.WasModified())
+        self.check_messages([(self.poly_layer, LAYER_CHANGED),
+                             (self.session, CHANGED)])
+
+    def test_forwarding_stroke_width(self):
+        """Test Session's forwarding of Layer.SetStrokeWidth messages"""
+        self.poly_layer.GetClassification().SetDefaultLineWidth(3)
+        self.assert_(self.session.WasModified())
+        self.check_messages([(self.poly_layer, LAYER_CHANGED),
+                             (self.session, CHANGED)])
+
+    def test_forwarding_visibility(self):
+        """Test Session's forwarding of Layer.SetVisible messages"""
+        self.poly_layer.SetVisible(0)
+        # Currently changing the visibility of a layer doesn't change
+        # the modification flag.
+        self.failIf(self.session.WasModified())
+        self.check_messages([(self.poly_layer, LAYER_VISIBILITY_CHANGED),
+                             (self.session, CHANGED)])
+
+    def test_unset_modified_map(self):
+        """Test Session.UnsetModified with map level changes"""
+        self.failIf(self.session.WasModified())
+        proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
+        self.map.SetProjection(proj)
+        self.assert_(self.session.WasModified())
+        self.session.UnsetModified()
+        self.failIf(self.session.WasModified())
+
+    def test_unset_modified_layer(self):
+        """Test Session.UnsetModified with layer level changes"""
+        self.failIf(self.session.WasModified())
+        self.poly_layer.GetClassification().SetDefaultLineWidth(3)
+        self.assert_(self.session.WasModified())
+        self.session.UnsetModified()
+        self.failIf(self.session.WasModified())
+        self.check_messages([(self.poly_layer, LAYER_CHANGED),
+                             (self.session, CHANGED),
+                             (CHANGED,)])
+
+    def test_shape_stores(self):
+        """Test Session.ShapeStores()"""
+        # Strictly speaking the session doesn't make guarantees about
+        # the order of the ShapeStores in the list, but currently it's
+        # deterministic and they're listed in the order in which they
+        # were created
+        self.assertEquals(self.session.ShapeStores(),
+                          [self.arc_layer.ShapeStore(),
+                           self.poly_layer.ShapeStore()])
+        # If we remove the map from the session and clear our instance
+        # variables that hold the layers and the map the list should
+        # become empty again.
+        self.session.RemoveMap(self.map)
+        self.arc_layer = self.poly_layer = self.map = None
+        self.assertEquals(self.session.ShapeStores(), [])
+
+    def test_tables(self):
+        """Test Session.Tables()"""
+        # Strictly speaking the session doesn't make guarantees about
+        # the order of the tables in the list, but currently it's
+        # deterministic and they're listed in the order in which they
+        # were opened
+        self.assertEquals(self.session.Tables(),
+                          [self.arc_layer.ShapeStore().Table(),
+                           self.poly_layer.ShapeStore().Table()])
+        # If we remove the map from the session and clear our instance
+        # variables that hold the layers and the map the list should
+        # become empty again.
+        self.session.RemoveMap(self.map)
+        self.arc_layer = self.poly_layer = self.map = None
+        self.assertEquals(self.session.Tables(), [])
+
+
+if __name__ == "__main__":
+    unittest.main()

Added: packages/thuban/branches/upstream/current/test/test_shapefilestore.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_shapefilestore.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_shapefilestore.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,220 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Test cases for ShapefileStore"""
+
+__version__ = "$Revision: 1675 $"
+# $Source$
+# $Id: test_shapefilestore.py 1675 2003-08-28 13:09:48Z bh $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.data import ShapefileStore
+from Thuban.Model.session import Session
+from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
+from Thuban.Model.data import RAW_SHAPEFILE
+
+
+class TestShapefileStore(unittest.TestCase):
+
+    """Test cases for ShapefileStore"""
+
+    def setUp(self):
+        """Initialize self.session"""
+        self.session = Session("Test Session")
+        self.filename = os.path.join("..", "Data", "iceland",
+                                "roads-line.shp")
+        self.store = ShapefileStore(self.session, self.filename)
+
+    def tearDown(self):
+        """Call self.session.Destroy() and reset self.session to None"""
+        self.session.Destroy()
+        self.session = None
+
+    def test_accessors(self):
+        """Test ShapefileStore accessors"""
+        self.assertEquals(self.store.FileName(),
+                          os.path.abspath(self.filename))
+
+        # The filetype of a shapefile is "shapefile"
+        self.assertEquals(self.store.FileType(), "shapefile")
+
+    def test_raw_format(self):
+        """Test ShapefileStore raw shape format"""
+        self.assertEquals(self.store.RawShapeFormat(), RAW_SHAPEFILE)
+
+        # For shapefiles the raw format means just the shape id as an
+        # int
+        self.assertEquals(self.store.Shape(5).RawData(), 5)
+
+    def test_dependencies(self):
+        """Test ShapefileStore and ShapeTable dependencies"""
+        # The shapestore itself depends on nothing else
+        self.assertEquals(self.store.Dependencies(), ())
+
+        # The shapestore's table depends on the shapestore
+        self.assertEquals(self.store.Table().Dependencies(), (self.store,))
+
+
+    def test_orig_shapestore(self):
+        """Test ShapefileStore.OrigShapeStore()"""
+        self.assertEquals(self.store.OrigShapeStore(), None)
+
+
+
+class ShapefileStoreTests(unittest.TestCase, support.FloatComparisonMixin):
+
+    """Base class for the ShapefileStore tests"""
+
+
+class TestShapefileStoreArc(ShapefileStoreTests):
+
+    """Test cases for ShapefileStore with arc shapes"""
+
+    def setUp(self):
+        """Initialize self.session"""
+        self.session = Session("Test Session")
+        self.filename = os.path.join("..", "Data", "iceland",
+                                "roads-line.shp")
+        self.store = ShapefileStore(self.session, self.filename)
+
+    def tearDown(self):
+        """Call self.session.Destroy() and reset self.session to None"""
+        self.session.Destroy()
+        self.session = None
+
+    def test_shape_type(self):
+        """Test ShapefileStore.ShapeType() with arc shapes"""
+        self.assertEquals(self.store.ShapeType(), SHAPETYPE_ARC)
+
+    def test_boundingbox(self):
+        """Test ShapefileStore.BoundingBox() with arc shapes"""
+        self.assertFloatSeqEqual(self.store.BoundingBox(),
+                                 [-24.450359344482422, 63.426830291748047,
+                                  -13.55668830871582, 66.520111083984375])
+
+    def test_num_shapes(self):
+        """Test ShapefileStore.NumShapes() with arc shapes"""
+        self.assertEquals(self.store.NumShapes(), 839)
+
+    def test_shapes_in_region(self):
+        """Test ShapefileStore.ShapesInRegion() with arc shapes"""
+        shapes = self.store.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
+        self.assertEquals([s.ShapeID() for s in shapes], [613, 726, 838])
+
+    def test_shape(self):
+        """Test ShapefileStore.Shape() with arc shapes"""
+        self.assertPointListEquals(self.store.Shape(32).Points(),
+                                   [[(-15.0821743011474, 66.2773818969726),
+                                     (-15.0263500213623, 66.2733917236328)]])
+
+    def test_shape_shapeid(self):
+        """Test ShapefileStore.Shape(i).ShapeID()"""
+        self.assertEquals(self.store.Shape(5).ShapeID(), 5)
+
+
+class TestShapefileStorePolygon(ShapefileStoreTests):
+
+    """Test cases for ShapefileStore with plygon shapes"""
+
+    def setUp(self):
+        """Initialize self.session"""
+        self.session = Session("Test Session")
+        """Test ShapeStore with polygon shapes"""
+        self.filename = os.path.join("..", "Data", "iceland",
+                                "political.shp")
+        self.store = ShapefileStore(self.session, self.filename)
+
+    def tearDown(self):
+        """Call self.session.Destroy() and reset self.session to None"""
+        self.session.Destroy()
+        self.session = None
+
+    def test_shape_type(self):
+        """Test ShapeStore.ShapeType() with polygon shapes"""
+        self.assertEquals(self.store.ShapeType(), SHAPETYPE_POLYGON)
+
+    def test_boundingbox(self):
+        """Test ShapefileStore.BoundingBox() with polygon shapes"""
+        self.assertFloatSeqEqual(self.store.BoundingBox(),
+                                 [-24.546524047851562, 63.286754608154297,
+                                  -13.495815277099609, 66.563774108886719])
+
+    def test_num_shapes(self):
+        """Test ShapefileStore.NumShapes() with polygon shapes"""
+        self.assertEquals(self.store.NumShapes(), 156)
+
+    def test_shapes_in_region(self):
+        """Test ShapefileStore.ShapesInRegion() with polygon shapes"""
+        shapes = self.store.ShapesInRegion((-24.0, 64.0, -23.9, 64.1))
+        self.assertEquals([s.ShapeID() for s in shapes],
+                          [91, 92, 144, 146, 148, 150, 152, 153])
+
+    def test_shape(self):
+        """Test ShapefileStore.Shape() with polygon shapes"""
+        self.assertPointListEquals(self.store.Shape(4).Points(),
+                                   [[(-22.40639114379882, 64.714111328125),
+                                     (-22.41621208190918, 64.716003417968),
+                                     (-22.40605163574218, 64.719200134277),
+                                     (-22.40639114379882, 64.714111328125)]])
+
+class TestShapefileStorePoint(ShapefileStoreTests):
+
+    """Test cases for ShapefileStore with plygon shapes"""
+
+    def setUp(self):
+        """Initialize self.session"""
+        self.session = Session("Test Session")
+        """Test ShapeStore with point shapes"""
+        self.filename = os.path.join("..", "Data", "iceland",
+                                "cultural_landmark-point.shp")
+        self.store = ShapefileStore(self.session, self.filename)
+
+    def tearDown(self):
+        """Call self.session.Destroy() and reset self.session to None"""
+        self.session.Destroy()
+        self.session = None
+
+    def test_shape_type(self):
+        """Test ShapeStore.ShapeType() with point shapes"""
+        self.assertEquals(self.store.ShapeType(), SHAPETYPE_POINT)
+
+    def test_boundingbox(self):
+        """Test ShapefileStore.BoundingBox() with point shapes"""
+        self.assertFloatSeqEqual(self.store.BoundingBox(),
+                                 [-23.806047439575195, 63.405960083007812,
+                                  -15.12291431427002, 66.36572265625])
+
+    def test_num_shapes(self):
+        """Test ShapefileStore.NumShapes() with point shapes"""
+        self.assertEquals(self.store.NumShapes(), 34)
+
+    def test_shapes_in_region(self):
+        """Test ShapefileStore.ShapesInRegion() with point shapes"""
+        shapes = self.store.ShapesInRegion((-24.0, 64.0, -23.80, 64.1))
+        self.assertEquals([s.ShapeID() for s in shapes],
+                          [0, 1, 2, 3, 4, 5, 27, 28, 29, 30, 31])
+
+    def test_all_shapes(self):
+        """Test ShapefileStore.AllShapes()"""
+        # This test is probably not needed for other shape types as it's
+        # not specific to the type or the data at all.
+        self.assertEquals([s.ShapeID() for s in self.store.AllShapes()],
+                          range(self.store.NumShapes()))
+
+    def test_shape(self):
+        """Test ShapefileStore.Shape() with point shapes"""
+        self.assertPointListEquals(self.store.Shape(0).Points(),
+                                   [[(-22.711074829101562, 66.36572265625)]])
+
+if __name__ == "__main__":
+    support.run_tests()
+

Added: packages/thuban/branches/upstream/current/test/test_stringrepresentation.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_stringrepresentation.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_stringrepresentation.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,40 @@
+# Copyright (c) 2005 by Intevation GmbH
+# Authors:
+# Bernhard Reiter <bernhard at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the functions for Thuban's string representation.
+"""
+
+__version__ = "$Revision: 2673 $"
+# $Source$
+# $Id: test_stringrepresentation.py 2673 2005-10-19 08:08:29Z bernhard $
+
+import unittest
+
+import support
+support.initthuban()
+
+import Thuban
+
+class TestInternalEncoding(unittest.TestCase):
+    """Test around the thuban default encoding."""
+
+    def setUp(self):
+        """Save the old internal encoding, so we can restore it."""
+        self.saved_encoding=Thuban.get_internal_encoding()
+
+    def tearDown(self):
+        """Restore saved internal encoding."""
+        Thuban.set_internal_encoding(self.saved_encoding)
+
+    def test_notice_bad_internalencoding(self):
+        bad_encoding="this-never-is-a-valid-encoding"
+        self.assertRaises(LookupError, 
+            Thuban.set_internal_encoding,bad_encoding)
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_transientdb.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_transientdb.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_transientdb.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,415 @@
+# Copyright (c) 2002, 2003, 2006 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the Transient DB classes
+"""
+
+__version__ = "$Revision: 2705 $"
+# $Source$
+# $Id: test_transientdb.py 2705 2006-09-24 18:55:30Z bernhard $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+import dbflib
+from Thuban.Model.table import DBFTable, MemoryTable, FIELDTYPE_STRING, \
+                               FIELDTYPE_INT, FIELDTYPE_DOUBLE, table_to_dbf
+from Thuban.Model.transientdb import TransientDatabase, TransientTable, \
+     TransientJoinedTable, AutoTransientTable
+
+
+class TestTransientTable(unittest.TestCase, support.FileTestMixin):
+
+    def setUp(self):
+        """Create a transient database as self.transientdb"""
+        filename = self.temp_file_name("transient_table.sqlite")
+        if os.path.exists(filename):
+            os.remove(filename)
+        journal = filename + "-journal"
+        if os.path.exists(journal):
+            print "removing journal", journal
+            os.remove(journal)
+        self.transientdb = TransientDatabase(filename)
+
+    def tearDown(self):
+        self.transientdb.close()
+
+    def run_iceland_political_tests(self, table):
+        """Run some tests on table
+
+        Assume that table holds the data of the file
+        ../Data/iceland/political.dbf sample file.
+        """
+        self.assertEquals(table.NumRows(), 156)
+        self.assertEquals(table.NumColumns(), 8)
+
+        # Check one each of the possible field types.
+        columns = table.Columns()
+        self.assertEquals(columns[0].name, 'AREA')
+        self.assertEquals(columns[0].type, FIELDTYPE_DOUBLE)
+        self.assertEquals(columns[3].name, 'PONET_ID')
+        self.assertEquals(columns[3].type, FIELDTYPE_INT)
+        self.assertEquals(columns[6].name, 'POPYCOUN')
+        self.assertEquals(columns[6].type, FIELDTYPE_STRING)
+
+        # HasColumn
+        self.failUnless(table.HasColumn("AREA"))
+        self.failUnless(table.HasColumn(1))
+        # HasColumn for non-exisiting columns
+        self.failIf(table.HasColumn("non_existing_name"))
+        self.failIf(table.HasColumn(100))
+
+        # Reading rows and values.
+        self.assertEquals(table.ReadRowAsDict(144),
+                          {'POPYCOUN': 'IC', 'POPYADMIN': '', 'PONET_': 146,
+                           'AREA': 19.462,
+                           'POPYTYPE': 1, 'PERIMETER': 88.518000000000001,
+                           'POPYREG': '1',
+                           'PONET_ID': 145})
+        self.assertEquals(table.ReadRowAsDict(144, row_is_ordinal = 1),
+                          {'POPYCOUN': 'IC', 'POPYADMIN': '', 'PONET_': 146,
+                           'AREA': 19.462,
+                           'POPYTYPE': 1, 'PERIMETER': 88.518000000000001,
+                           'POPYREG': '1',
+                           'PONET_ID': 145})
+        self.assertEquals(table.ReadValue(144, "AREA"), 19.462)
+        self.assertEquals(table.ReadValue(144, 3), 145)
+        self.assertEquals(table.ReadValue(144, "AREA", row_is_ordinal = 1),
+                          19.462)
+        self.assertEquals(table.ReadValue(144, 3, row_is_ordinal = 1), 145)
+
+        self.assertEquals(table.RowIdToOrdinal(23), 23)
+        self.assertEquals(table.RowOrdinalToId(23), 23)
+
+        # ValueRange may induce a copy to the transient database.
+        # Therefore we put it last so that we can execute this method
+        # twice to check whether the other methods still work after the
+        # copy
+        self.assertEquals(table.ValueRange("AREA"), (0.0, 19.462))
+
+        unique = table.UniqueValues("PONET_ID")
+        unique.sort()
+        self.assertEquals(unique, range(1, 157))
+
+    def test_transient_table(self):
+        """Test TransientTable(dbftable)
+
+        The TransientTable should copy the data to the
+        TransientDatabase.
+        """
+        orig_table = DBFTable(os.path.join("..", "Data", "iceland",
+                                           "political.dbf"))
+        table = TransientTable(self.transientdb, orig_table)
+        self.run_iceland_political_tests(table)
+
+        # The transient_table method should return the table itself
+        self.assert_(table is table.transient_table())
+
+        # The title is simply copied over from the original table
+        self.assertEquals(table.Title(), orig_table.Title())
+
+        # The TransientTable class itself doesn't implement the
+        # Dependencies method, so we don't test it.
+
+
+    def test_auto_transient_table(self):
+        """Test AutoTransientTable(dbftable)
+
+        The AutoTransientTable should copy the data to the
+        TransientDatabase on demand.
+        """
+        orig_table = DBFTable(os.path.join("..", "Data", "iceland",
+                                           "political.dbf"))
+        table = AutoTransientTable(self.transientdb, orig_table)
+
+        # Run the tests twice so that we execute them once when the data
+        # has not been copied to the transient db yet and once when it
+        # has. This assumes that run_iceland_political_tests does at
+        # least one call to a method that copies to the transient db at
+        # its end.
+        self.run_iceland_political_tests(table)
+        # At this point the data has probably not been copied to the
+        # transient DB yet, so we force it by calling the
+        # transient_table method.
+        table.transient_table()
+
+        # Run the tests again.
+        self.run_iceland_political_tests(table)
+
+    def test_auto_transient_table_query(self):
+        """Test AutoTransientTable.SimpleQuery()"""
+        orig_table = DBFTable(os.path.join("..", "Data", "iceland",
+                                           "political.dbf"))
+        table = AutoTransientTable(self.transientdb, orig_table)
+        # Only a simple test here. The AutoTransientTable simply
+        # delegates to its transient table so it should be OK that the
+        # real test for it is in test_transient_table_query. However,
+        # it's important to check that the column handling works
+        # correctly because the AutoTransientTable and it's underlying
+        # transient table use different column object types.
+        self.assertEquals(table.SimpleQuery(table.Column("AREA"), ">", 10.0),
+                          [144])
+
+        # test using a Column object as the right parameter
+        self.assertEquals(table.SimpleQuery(table.Column("POPYTYPE"),
+                                            "==",
+                                            table.Column("POPYREG")),
+                          range(156))
+
+    def test_auto_transient_table_dependencies(self):
+        """Test AutoTransientTable.Dependencies()"""
+        orig_table = DBFTable(os.path.join("..", "Data", "iceland",
+                                           "political.dbf"))
+        table = AutoTransientTable(self.transientdb, orig_table)
+        self.assertEquals(table.Dependencies(), (orig_table,))
+
+    def test_auto_transient_table_title(self):
+        """Test AutoTransientTable.Title()"""
+        orig_table = DBFTable(os.path.join("..", "Data", "iceland",
+                                           "political.dbf"))
+        table = AutoTransientTable(self.transientdb, orig_table)
+        # The title is of course the same as that of the original table
+        self.assertEquals(table.Title(), orig_table.Title())
+
+    def test_transient_joined_table(self):
+        """Test TransientJoinedTable"""
+        simple = MemoryTable([("type", FIELDTYPE_STRING),
+                              ("code", FIELDTYPE_INT)],
+                             [("OTHER/UNKNOWN", 0),
+                              ("RUINS", 1),
+                              ("FARM", 2),
+                              ("BUILDING", 3),
+                              ("HUT", 4),
+                              ("LIGHTHOUSE", 5)])
+        auto = AutoTransientTable(self.transientdb, simple)
+        filename = os.path.join("..", "Data", "iceland",
+                                "cultural_landmark-point.dbf")
+        landmarks = AutoTransientTable(self.transientdb, DBFTable(filename))
+
+        table = TransientJoinedTable(self.transientdb, landmarks, "CLPTLABEL",
+                                     auto, "type")
+
+        self.assertEquals(table.NumRows(), 34)
+        self.assertEquals(table.NumColumns(), 8)
+        self.assertEquals(table.Column(0).type, FIELDTYPE_DOUBLE)
+        self.assertEquals(table.Column(0).name, 'AREA')
+        self.assertEquals(table.Column(7).type, FIELDTYPE_INT)
+        self.assertEquals(table.Column(7).name, 'code')
+        self.assertEquals(table.Column(4).type, FIELDTYPE_STRING)
+        self.assertEquals(table.Column(4).name, 'CLPTLABEL')
+        # HasColumn
+        self.failUnless(table.HasColumn("AREA"))
+        self.failUnless(table.HasColumn(1))
+        # HasColumn for non-exisiting columns
+        self.failIf(table.HasColumn("non_existing_name"))
+        self.failIf(table.HasColumn(100))
+
+        # Reading rows and values
+        self.assertEquals(table.ReadRowAsDict(22),
+                          {'PERIMETER': 0.0, 'CLPOINT_': 23,
+                           'AREA': 0.0, 'CLPTLABEL': 'RUINS',
+                           'CLPOINT_ID': 38, 'CLPTFLAG': 0,
+                           'code': 1, 'type': 'RUINS'})
+        self.assertEquals(table.ReadValue(22, "type"), 'RUINS')
+        self.assertEquals(table.ReadValue(22, 7), 1)
+        self.assertEquals(table.ReadValue(22, "type", row_is_ordinal = 1),
+                          "RUINS")
+        self.assertEquals(table.ReadValue(22, 7, row_is_ordinal = 1), 1)
+        self.assertEquals(table.RowIdToOrdinal(23), 23)
+        self.assertEquals(table.RowOrdinalToId(23), 23)
+
+        # The transient_table method should return the table itself
+        self.assert_(table is table.transient_table())
+
+        # The TransientJoinedTable depends on both input tables
+        self.assertEquals(table.Dependencies(), (landmarks, auto))
+
+        # The title is constructed from the titles of the input tables.
+        self.assertEquals(table.Title(),
+                          "Join of %s and %s" % (landmarks.Title(),
+                                                 auto.Title()))
+
+
+    def test_transient_joined_table_same_column_name(self):
+        """Test TransientJoinedTable join on columns with same name
+
+        The transient DB maps the column names used by the tables to
+        another set of names used only inside the SQLite database. There
+        was a bug in the way this mapping was used when joining on
+        fields with the same names in both tables so that the joined
+        table ended up joining on the same column in the same table.
+        """
+        mem_stretches = MemoryTable([("stretch_id", FIELDTYPE_INT)],
+                                    [(i,) for i in range(4)])
+        stretches = AutoTransientTable(self.transientdb, mem_stretches)
+
+        mem_discharges = MemoryTable([("disch_id", FIELDTYPE_INT),
+                                      ("stretch_id", FIELDTYPE_INT)],
+                                     [(1, 0), (2, 3)])
+        discharges = AutoTransientTable(self.transientdb, mem_discharges)
+
+        table = TransientJoinedTable(self.transientdb, stretches, "stretch_id",
+                                     discharges, "stretch_id",
+                                     outer_join = True)
+
+        self.assertEquals(table.NumRows(), 4)
+        self.assertEquals(table.NumColumns(), 3)
+
+        # HasColumn
+        self.failUnless(table.HasColumn("stretch_id"))
+        self.failUnless(table.HasColumn("disch_id"))
+
+
+    def test_transient_joined_table_with_equal_column_names(self):
+        """Test TransientJoinedTable join on tables with equal column names
+
+        If a name collision occurs for the field names, underscores are
+        appended as long as any collision is resolved.
+        """
+        mem_stretches = MemoryTable([("stretch_id", FIELDTYPE_INT),
+                                     ("name", FIELDTYPE_INT)],
+                                    [(0, 10), (1, 11), (2, 12), (3, 13) ])
+        stretches = AutoTransientTable(self.transientdb, mem_stretches)
+
+        mem_discharges = MemoryTable([("disch_id", FIELDTYPE_INT),
+                                      ("stretch_id", FIELDTYPE_INT),
+                                      ("name", FIELDTYPE_INT)],
+                                     [(1, 0, 1), (2, 3, 2)])
+        discharges = AutoTransientTable(self.transientdb, mem_discharges)
+
+        table = TransientJoinedTable(self.transientdb, stretches, "stretch_id",
+                                     discharges, "stretch_id",
+                                     outer_join = True)
+
+        self.assertEquals(table.NumRows(), 4)
+        self.assertEquals(table.NumColumns(), 5)
+
+        # HasColumn
+        self.assertEquals([c.name for c in table.Columns()],
+                          ["stretch_id", "name", "disch_id", "stretch_id_",
+                           "name_"])
+
+    def test_transient_joined_table_name_collisions_dont_modify_in_place(self):
+        """Test TransientJoinedTable name-collisions do not modifying in place
+
+        The name collision work-around by appending underscores
+        accidentally modified the column objects in place. We do two
+        joins therefore in reverse order to detect this: The first join
+        will lead to a modified name in the column object of the right
+        table which is then used as the left table in the second join so
+        the underscored name will appear before the non-underscored one
+        in the list of column names after the second join.
+        """
+        mem1 = MemoryTable([("stretch_id", FIELDTYPE_INT),
+                            ("name", FIELDTYPE_INT)],
+                           [(0, 10), (1, 11), (2, 12), (3, 13) ])
+        table1 = AutoTransientTable(self.transientdb, mem1)
+
+        mem2 = MemoryTable([("stretch_id", FIELDTYPE_INT),
+                            ("name", FIELDTYPE_INT)],
+                           [(0, 10), (1, 11), (2, 12), (3, 13) ])
+        table2 = AutoTransientTable(self.transientdb, mem2)
+
+        table = TransientJoinedTable(self.transientdb, table1, "stretch_id",
+                                     table2, "stretch_id", outer_join = True)
+        table = TransientJoinedTable(self.transientdb, table2, "stretch_id",
+                                     table1, "stretch_id", outer_join = True)
+
+        self.assertEquals([c.name for c in table.Columns()],
+                          ["stretch_id", "name", "stretch_id_", "name_"])
+
+    def test_transient_table_read_twice(self):
+        """Test TransientTable.ReadRowAsDict() reading the same record twice"""
+        simple = MemoryTable([("type", FIELDTYPE_STRING),
+                              ("code", FIELDTYPE_INT)],
+                             [("OTHER/UNKNOWN", 0),
+                              ("RUINS", 1),
+                              ("FARM", 2),
+                              ("BUILDING", 3),
+                              ("HUT", 4),
+                              ("LIGHTHOUSE", 5)])
+        table = TransientTable(self.transientdb, simple)
+
+        # There was a bug where reading the same record twice would
+        # raise an exception in the second call because of an
+        # unitialized local variable, so for passing the test it's
+        # enough if reading simply succeeds. OTOH, while we're at it we
+        # might as well check whether the results are equal anyway :)
+        result1 = table.ReadRowAsDict(3)
+        result2 = table.ReadRowAsDict(3)
+        self.assertEquals(result1, result2)
+
+
+    def test_transient_table_query(self):
+        """Test TransientTable.SimpleQuery()"""
+        simple = MemoryTable([("type", FIELDTYPE_STRING),
+                              ("value", FIELDTYPE_DOUBLE),
+                              ("code", FIELDTYPE_INT)],
+                             [("OTHER/UNKNOWN", -1.5, 11),
+                              ("RUINS", 0.0, 1),
+                              ("FARM", 3.141, 2),
+                              ("BUILDING", 2.5, 3),
+                              ("HUT", 1e6, 4),
+                              ("LIGHTHOUSE", -0.01, 5)])
+        table = TransientTable(self.transientdb, simple)
+
+        # A column and a value
+        self.assertEquals(table.SimpleQuery(table.Column(0), "==", "RUINS"),
+                          [1])
+        self.assertEquals(table.SimpleQuery(table.Column(2), "!=", 2),
+                          [0, 1, 3, 4, 5])
+        self.assertEquals(table.SimpleQuery(table.Column(1), "<", 1.0),
+                          [0, 1, 5])
+        self.assertEquals(table.SimpleQuery(table.Column(1), "<=", -1.5),
+                          [0])
+        self.assertEquals(table.SimpleQuery(table.Column(2), ">", 3),
+                          [0, 4, 5])
+        self.assertEquals(table.SimpleQuery(table.Column(2), ">=", 3),
+                          [0, 3, 4, 5])
+
+        # Two columns as operands
+        self.assertEquals(table.SimpleQuery(table.Column(1),
+                                            "<=", table.Column(2)),
+                          [0, 1, 3, 5])
+
+        # Test whether invalid operators raise a ValueError
+        self.assertRaises(ValueError,
+                          table.SimpleQuery,
+                          table.Column(1), "<<", table.Column(2))
+
+    def test_transienttable_to_dbf(self):
+        memtable = MemoryTable([("type", FIELDTYPE_STRING),
+                                ("value", FIELDTYPE_DOUBLE),
+                                ("code", FIELDTYPE_INT)],
+                               [("UNKNOWN", 0.0, 0),
+                                ("Foo", 0.5, -1),
+                                ("Foo", 1.0/256, 100),
+                                ("bar", 1e10, 17)])
+        table = TransientTable(self.transientdb, memtable)
+        filename = self.temp_file_name("test_transienttable_to_dbf.dbf")
+        table_to_dbf(table, filename)
+
+        dbf = dbflib.DBFFile(filename)
+        self.assertEquals(dbf.read_record(2),
+                          {'code': 100, 'type': 'Foo', 'value': 0.00390625})
+        self.assertEquals(dbf.field_count(), 3)
+        self.assertEquals(dbf.record_count(), 4)
+        self.assertEquals(dbf.field_info(0),
+                          (dbflib.FTString, "type", 7, 0))
+        self.assertEquals(dbf.field_info(1),
+                          (dbflib.FTDouble, "value", 24, 12))
+        self.assertEquals(dbf.field_info(2),
+                          (dbflib.FTInteger, "code", 3, 0))
+
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_viewport.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_viewport.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_viewport.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,509 @@
+# Copyright (c) 2003, 2004 by Intevation GmbH
+# Authors:
+# Jonathan Coles <jonathan at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Test the interaction with the view
+"""
+
+__version__ = "$Revision: 2297 $"
+# $Source$
+# $Id: test_viewport.py 2297 2004-07-22 13:07:52Z bh $
+
+import os
+import unittest
+
+import postgissupport
+import support
+support.initthuban()
+
+from Thuban.UI.viewport import ViewPort, ZoomInTool, ZoomOutTool, \
+                               PanTool, IdentifyTool, LabelTool
+
+from Thuban.Model.map import Map
+from Thuban.Model.proj import Projection
+from Thuban.Model.layer import Layer
+from Thuban.Model.session import Session
+from Thuban.Model.color import Color
+from Thuban.Model.postgisdb import PostGISConnection
+from Thuban.UI.messages import SCALE_CHANGED, MAP_REPLACED
+from Thuban.Model.messages import TITLE_CHANGED
+
+class Event:
+    pass
+
+
+class MockView(ViewPort):
+
+    def GetTextExtent(self, text):
+        """Mock implementation so that the test cases work"""
+        # arbitrary numbers, really just so the tests pass
+        return 40, 20
+
+
+
+class SimpleViewPortTest(unittest.TestCase):
+
+    """Simple ViewPort tests"""
+
+    def test_default_size(self):
+        """Test ViewPort default size and scale"""
+        port = ViewPort()
+        try:
+            self.assertEquals(port.GetPortSizeTuple(), (400, 300))
+            self.assertEquals(port.scale, 1.0)
+            self.assertEquals(port.offset, (0, 0))
+            self.assertEquals(port.VisibleExtent(), (0.0, -300.0, 400.0, 0.0))
+        finally:
+            port.Destroy()
+
+    def test_init_with_size(self):
+        """Test ViewPort(<size>)"""
+        port = ViewPort((1001, 1001))
+        try:
+            self.assertEquals(port.GetPortSizeTuple(), (1001, 1001))
+            self.assertEquals(port.VisibleExtent(), (0.0, -1001.0, 1001.0, 0.0))
+        finally:
+            port.Destroy()
+
+    def test_visible_extent(self):
+        """Test ViewPort.VisibleExtent()"""
+        class MockMap:
+            def ProjectedBoundingBox(self):
+                return (500, 400, 600, 500)
+            # noops that the viewport expects but which aren't needed
+            # here:
+            Subscribe = Unsubscribe = lambda *args: None
+
+        map = MockMap()
+        port = ViewPort((1000, 1000))
+        try:
+            port.SetMap(map)
+            # The viewport adjusts automatically to the map.  Since both
+            # the map's bounding box and the viewport are square the map
+            # fits exactly.
+            self.assertEquals(port.VisibleExtent(), (500, 400, 600, 500))
+
+            # Zoom in a bit
+            port.ZoomFactor(2)
+            self.assertEquals(port.VisibleExtent(), (525, 425, 575, 475))
+        finally:
+            port.Destroy()
+
+
+class ViewPortTest(unittest.TestCase, support.SubscriberMixin,
+                   support.FloatComparisonMixin):
+
+    def build_path(self, filename):
+        return os.path.join("..", "Data", "iceland", filename)
+
+    def open_shapefile(self, filename):
+        """Open and return a shapestore for filename in the iceland data set"""
+        return self.session.OpenShapefile(self.build_path(filename))
+
+    def setUp(self):
+        self.session = Session("Test session for %s" % self.__class__)
+
+        # make view port 1001x1001 so we have an exact center
+        self.port = MockView((1001, 1001))
+
+        proj = Projection(["proj=latlong", 
+                           "to_meter=.017453292519943",
+                           "ellps=clrk66"])
+
+        self.map = map = Map("title", proj)
+        layer = Layer("Polygon", self.open_shapefile("political.shp"))
+        layer.GetClassification().GetDefaultGroup()\
+                        .GetProperties().SetFill(Color(0,0,0))
+        map.AddLayer(layer)
+        layer = Layer("Point",
+                      self.open_shapefile("cultural_landmark-point.shp"))
+        layer.GetClassification().GetDefaultGroup()\
+                        .GetProperties().SetFill(Color(0,0,0))
+        map.AddLayer(layer)
+        layer = Layer("Arc", self.open_shapefile("roads-line.shp"))
+        layer.GetClassification().GetDefaultGroup()\
+                        .GetProperties().SetFill(Color(0,0,0))
+        map.AddLayer(layer)
+        self.session.AddMap(map)
+
+        self.layer = layer
+
+        self.port.SetMap(map)
+        for msg in (SCALE_CHANGED, MAP_REPLACED, TITLE_CHANGED):
+            self.port.Subscribe(msg, self.subscribe_with_params, msg)
+        self.clear_messages()
+
+    def tearDown(self):
+        self.port.Destroy()
+        self.session.Destroy()
+        self.map = self.session = self.port = self.layer = None
+
+    def test_inital_settings(self):
+        self.failIf(self.port.HasSelectedLayer())
+        self.failIf(self.port.HasSelectedShapes())
+
+    def test_win_to_proj(self):
+        self.assertFloatSeqEqual(self.port.win_to_proj(0, 0),
+                                 (-24.546524047851978, 70.450618743897664))
+        self.assertFloatSeqEqual(self.port.win_to_proj(100, 0),
+                                 (-23.442557137686929, 70.450618743897664))
+        self.assertFloatSeqEqual(self.port.win_to_proj(0, 100),
+                                 (-24.546524047851978, 69.346651833732622))
+
+    def test_proj_to_win(self):
+        self.assertFloatSeqEqual(self.port.proj_to_win(-24.546524047851978,
+                                                       70.450618743897664),
+                                 (0, 0))
+        self.assertFloatSeqEqual(self.port.proj_to_win(-23.442557137686929,
+                                                       70.450618743897664),
+                                 (100, 0))
+        self.assertFloatSeqEqual(self.port.proj_to_win(-24.546524047851978,
+                                                       69.346651833732622),
+                                 (0, 100))
+
+    def test_set_map(self):
+        """Test ViewPort.SetMap()"""
+        # The port already has a map. So we set it to None before we set
+        # it to self.map again.
+
+        # Setting the map to None does not change the scale, but it will
+        # issue a MAP_REPLACED message.
+        self.port.SetMap(None)
+        self.check_messages([(MAP_REPLACED,)])
+
+        self.clear_messages()
+
+        self.port.SetMap(self.map)
+        self.check_messages([(90.582425142660739, SCALE_CHANGED),
+                             (MAP_REPLACED,)])
+
+    def test_changing_map_projection(self):
+        """Test ViewPort behavior when changing the map's projection
+
+        The viewport subscribe's to the map's MAP_PROJECTION_CHANGED
+        messages and tries to adjust the viewport when the projection
+        changes to make sure the map is still visible in the window.
+        There was a bug at one point where the viewport couldn't cope
+        with the map not having a meaningful bounding box in this
+        situation.
+        """
+        # Create a projection and an empty map.  We can't use self.map
+        # here because we do need an empty one.
+        themap = Map("title", Projection(["proj=latlong",
+                                          "to_meter=.017453292519943",
+                                          "ellps=clrk66"]))
+        # Add the map to self.session so that it's properly destroyed in
+        # tearDown()
+        self.session.AddMap(themap)
+
+        # Add the map to the view port and clear the messages.  Then
+        # we're set for the actual test.
+        self.port.SetMap(themap)
+        self.clear_messages()
+
+        # The test: set another projection.  The viewport tries to
+        # adjust the view so that the currently visible region stays
+        # visible.  The viewport has to take into account that the map
+        # is empty, which it didn't in Thuban/UI/viewport.py rev <= 1.16.
+        # This part of the test is OK when the SetProjection call does
+        # not lead to an exception.
+        themap.SetProjection(Projection(["proj=latlong",
+                                         "to_meter=.017453292519943",
+                                         "ellps=clrk66"]))
+
+        # If the map weren't empty the viewport might send SCALE_CHANGED
+        # messages, but it must no do so in this case because the scale
+        # doesn't change.
+        self.check_messages([])
+
+    def testFitRectToWindow(self):
+        rect = self.port.win_to_proj(9, 990) + self.port.win_to_proj(990, 9)
+        self.port.FitRectToWindow(rect)
+        self.assertFloatSeqEqual(rect, self.port.win_to_proj(0, 1000)
+                                 + self.port.win_to_proj(1000, 0), 1e-1)
+
+    def testZoomFactor(self):
+        self.port.FitMapToWindow()
+        rect = self.port.win_to_proj(9, 990) + self.port.win_to_proj(990, 9)
+        proj_rect = self.port.win_to_proj(0,1000)+self.port.win_to_proj(1000,0)
+        self.port.ZoomFactor(2)
+        self.port.ZoomFactor(.5)
+        self.assertFloatSeqEqual(rect,
+                                 self.port.win_to_proj(0, 1000)
+                                 + self.port.win_to_proj(1000, 0), 1)
+
+        point = self.port.win_to_proj(600, 600)
+        self.port.ZoomFactor(2, (600, 600))
+        self.assertFloatSeqEqual(point, self.port.win_to_proj(500, 500), 1e-3)
+        self.port.FitMapToWindow()
+
+        proj_rect = self.port.win_to_proj(-499, 1499)\
+                    + self.port.win_to_proj(1499, -499)
+        self.port.ZoomFactor(.5)
+        self.assertFloatSeqEqual(proj_rect,
+                                 self.port.win_to_proj(0, 1000)
+                                 + self.port.win_to_proj(1000, 0), 1)
+
+    def testZoomOutToRect(self):
+        self.port.FitMapToWindow()
+        rect   = self.port.win_to_proj(9, 990) + self.port.win_to_proj(990, 9)
+        rectTo = self.port.win_to_proj(0, 1000) + self.port.win_to_proj(1000,
+                                                                        0)
+        self.port.ZoomOutToRect(rect)
+        self.assertFloatSeqEqual(rect, rectTo, 1)
+
+    def testTranslate(self):
+        self.port.FitMapToWindow()
+        orig_rect = self.port.win_to_proj(0,1000)+self.port.win_to_proj(1000,0)
+        for delta in [(0, 0), (5, 0), (0, 5), (5,5),
+                      (-5, 0), (0, -5), (-5, -5)]:
+            rect = self.port.win_to_proj(0 + delta[0], 1000 + delta[1])  \
+                   + self.port.win_to_proj(1000 + delta[0], 0 + delta[1])
+            self.port.Translate(delta[0], delta[1])
+            self.assertFloatSeqEqual(rect,
+                                     self.port.win_to_proj(0, 1000)
+                                     + self.port.win_to_proj(1000, 0), 1)
+            self.port.Translate(-delta[0], -delta[1])
+            self.assertFloatSeqEqual(rect, orig_rect, 1)
+
+    def test_unprojected_rect_around_point(self):
+        rect = self.port.unprojected_rect_around_point(500, 500, 5)
+        self.assertFloatSeqEqual(rect,
+                                 (-19.063379161960469, 64.924498140752377, 
+                                  -18.95455127948528, 65.033326023227573),
+                                 1e-1)
+
+    def test_find_shape_at(self):
+        eq = self.assertEquals
+        x, y = self.port.proj_to_win(-18, 64.81418571)
+        eq(self.port.find_shape_at(x, y, searched_layer=self.layer),
+           (None, None))
+
+        x, y = self.port.proj_to_win(-18.18776318, 64.81418571)
+        eq(self.port.find_shape_at(x, y, searched_layer=self.layer),
+           (self.layer, 610))
+
+    def testLabelShapeAt(self):
+        eq = self.assertEquals
+
+        # select a road
+        x, y = self.port.proj_to_win(-18.18776318, 64.81418571)
+        eq(self.port.LabelShapeAt(x, y), False) # nothing to do
+        eq(self.port.LabelShapeAt(x, y, "Hello world"), True) # add
+        eq(self.port.LabelShapeAt(x, y), True) # remove
+
+        # select a point
+        x, y = self.port.proj_to_win(-19.140, 63.4055717)
+        eq(self.port.LabelShapeAt(x, y), False) # nothing to do
+        eq(self.port.LabelShapeAt(x, y, "Hello world"), True) # add
+        eq(self.port.LabelShapeAt(x, y), True) # remove
+
+        # select a polygon
+        x, y = self.port.proj_to_win(-16.75286628, 64.67807745)
+        eq(self.port.LabelShapeAt(x, y), False) # nothing to do
+        eq(self.port.LabelShapeAt(x, y, "Hello world"), True) # add
+        # for polygons the coordinates will be different, so
+        # these numbers were copied
+        x, y = self.port.proj_to_win(-18.5939850348, 64.990607973)
+        eq(self.port.LabelShapeAt(x, y), True) # remove
+
+
+    def test_set_pos(self):
+        eq = self.assertEquals
+        # set_current_position / CurrentPosition
+        event = Event()
+        event.m_x, event.m_y = 5, 5
+        self.port.set_current_position(event)
+        eq(self.port.current_position, (5, 5))
+        eq(self.port.CurrentPosition(), self.port.win_to_proj(5, 5))
+        self.port.set_current_position(None)
+        eq(self.port.current_position, None)
+        eq(self.port.CurrentPosition(), None)
+
+        event.m_x, event.m_y = 15, 15
+        self.port.MouseMove(event)
+        eq(self.port.current_position, (15, 15))
+        event.m_x, event.m_y = 25, 15
+        self.port.MouseLeftDown(event)
+        eq(self.port.current_position, (25, 15))
+        event.m_x, event.m_y = 15, 25
+        self.port.MouseLeftUp(event)
+        eq(self.port.current_position, (15, 25))
+
+    def testTools(self):
+        eq = self.assertEquals
+        event = Event()
+        def test_tools(tool, shortcut):
+            self.port.SelectTool(tool)
+            eq(self.port.CurrentTool(), tool.Name())
+            self.port.SelectTool(None)
+            eq(self.port.CurrentTool(), None)
+            shortcut()
+            eq(self.port.CurrentTool(), tool.Name())
+
+        test_tools(ZoomInTool(self.port), self.port.ZoomInTool)
+
+        point = self.port.win_to_proj(600, 600)
+
+        # one click zoom
+        event.m_x, event.m_y = 600, 600
+        self.port.MouseMove(event)
+        self.port.MouseLeftDown(event)
+        self.port.MouseLeftUp(event)
+        self.assertFloatSeqEqual(point, self.port.win_to_proj(500, 500), 1e-3)
+        self.port.FitMapToWindow()
+
+        # zoom rectangle
+        rect = self.port.win_to_proj(29, 970) + self.port.win_to_proj(970, 29)
+        event.m_x, event.m_y = 29, 29
+        self.port.MouseMove(event)
+        self.port.MouseLeftDown(event)
+        event.m_x, event.m_y = 970, 970
+        self.port.MouseMove(event)
+        self.port.MouseLeftUp(event)
+        self.assertFloatSeqEqual(rect,
+                                 self.port.win_to_proj(0, 1000)
+                                 + self.port.win_to_proj(1000, 0), 1e-1)
+        self.port.FitMapToWindow()
+
+        test_tools(ZoomOutTool(self.port), self.port.ZoomOutTool)
+
+        # one click zoom out
+        proj_rect = self.port.win_to_proj(-499, 1499) \
+                    + self.port.win_to_proj(1499, -499)
+        event.m_x, event.m_y = 500, 500
+        self.port.MouseMove(event)
+        self.port.MouseLeftDown(event)
+        self.port.MouseLeftUp(event)
+        self.assertFloatSeqEqual(proj_rect,
+                                 self.port.win_to_proj(0, 1000)
+                                 + self.port.win_to_proj(1000, 0),1e-1)
+        self.port.FitMapToWindow()
+
+        # zoom out rectangle
+        rect = self.port.win_to_proj(0, 1000) + self.port.win_to_proj(1000, 0)
+        event.m_x, event.m_y = 29, 29
+        self.port.MouseMove(event)
+        self.port.MouseLeftDown(event)
+        event.m_x, event.m_y = 970, 970
+        self.port.MouseMove(event)
+        self.port.MouseLeftUp(event)
+        self.assertFloatSeqEqual(rect,
+                                 self.port.win_to_proj(29, 970)
+                                 + self.port.win_to_proj(970, 29))
+        self.port.FitMapToWindow()
+
+        test_tools(PanTool(self.port), self.port.PanTool)
+
+        rect = self.port.win_to_proj(-25, 975) + self.port.win_to_proj(975,-25)
+        event.m_x, event.m_y = 50, 50
+        self.port.MouseMove(event)
+        self.port.MouseLeftDown(event)
+        event.m_x, event.m_y = 75, 75
+        self.port.MouseMove(event)
+        self.port.MouseLeftUp(event)
+        self.assertFloatSeqEqual(rect,
+                                 self.port.win_to_proj(0, 1000)
+                                 + self.port.win_to_proj(1000, 0))
+
+        test_tools(IdentifyTool(self.port), self.port.IdentifyTool)
+
+        event.m_x, event.m_y = self.port.proj_to_win(-18.18776318, 64.81418571)
+        self.port.MouseMove(event)
+        self.port.MouseLeftDown(event)
+        self.port.MouseLeftUp(event)
+        eq(self.port.SelectedShapes(), [610])
+
+        test_tools(LabelTool(self.port), self.port.LabelTool)
+
+        # since adding a label requires use interaction with a dialog
+        # we will insert a label and then only test whether clicking
+        # removes the label
+
+        x, y = self.port.proj_to_win(-19.140, 63.4055717)
+        self.port.LabelShapeAt(x, y, "Hello world")
+        event.m_x, event.m_y = x, y
+        self.port.MouseMove(event)
+        self.port.MouseLeftDown(event)
+        self.port.MouseLeftUp(event)
+        eq(self.port.LabelShapeAt(x, y), False) # should have done nothing
+
+    def test_forwarding_title_changed(self):
+        """Test whether ViewPort forwards the TITLE_CHANGED message of the map
+        """
+        self.map.SetTitle(self.map.Title() + " something to make it different")
+        self.check_messages([(self.map, TITLE_CHANGED)])
+
+
+class TestViewportWithPostGIS(unittest.TestCase):
+
+    def setUp(self):
+        """Start the server and create a database.
+
+        The database name will be stored in self.dbname, the server
+        object in self.server and the db object in self.db.
+        """
+        postgissupport.skip_if_no_postgis()
+        self.server = postgissupport.get_test_server()
+        self.dbref = self.server.get_default_static_data_db()
+        self.dbname = self.dbref.dbname
+        self.session = Session("PostGIS Session")
+        self.db = PostGISConnection(dbname = self.dbname,
+                                    **self.server.connection_params("user"))
+
+        proj = Projection(["proj=latlong",
+                           "to_meter=.017453292519943",
+                           "ellps=clrk66"])
+        self.map = Map("title", proj)
+
+        self.port = ViewPort((1001, 1001))
+
+    def tearDown(self):
+        self.session.Destroy()
+        self.port.Destroy()
+        self.map.Destroy()
+        self.map = self.port = None
+
+    def test_find_shape_at_point(self):
+        """Test ViewPort.find_shape_at() with postgis point layer"""
+        layer = Layer("Point",
+                      self.session.OpenDBShapeStore(self.db, "landmarks"))
+        prop = layer.GetClassification().GetDefaultGroup().GetProperties()
+        prop.SetFill(Color(0,0,0))
+        self.map.AddLayer(layer)
+
+        self.port.SetMap(self.map)
+
+        x, y = self.port.proj_to_win(-22.54335021, 66.30889129)
+        self.assertEquals(self.port.find_shape_at(x, y), (layer, 1001))
+
+    def test_find_shape_at_arc(self):
+        """Test ViewPort.find_shape_at() with postgis arc layer"""
+        layer = Layer("Arc", self.session.OpenDBShapeStore(self.db, "roads"))
+        self.map.AddLayer(layer)
+
+        self.port.SetMap(self.map)
+
+        x, y = self.port.proj_to_win(-18.18776318, 64.81418571)
+        self.assertEquals(self.port.find_shape_at(x, y), (layer, 610))
+
+    def test_find_shape_at_polygon(self):
+        """Test ViewPort.find_shape_at() with postgis polygon layer"""
+        layer = Layer("Poly",
+                      self.session.OpenDBShapeStore(self.db, "political"))
+        prop = layer.GetClassification().GetDefaultGroup().GetProperties()
+        prop.SetFill(Color(0,0,0))
+        self.map.AddLayer(layer)
+
+        self.port.SetMap(self.map)
+
+        x, y = self.port.proj_to_win(-19.78369, 65.1649143)
+        self.assertEquals(self.port.find_shape_at(x, y), (layer, 144))
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_wellknowntext.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_wellknowntext.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_wellknowntext.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,79 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Test Thuban.Model.wellknowntext"""
+
+__version__ = "$Revision: 1605 $"
+# $Source$
+# $Id: test_wellknowntext.py 1605 2003-08-19 11:00:40Z bh $
+
+import unittest
+
+import support
+support.initthuban()
+
+from Thuban.Model.wellknowntext import parse_wkt_thuban
+
+
+class TestWKT(unittest.TestCase, support.FloatComparisonMixin):
+
+    def test_point(self):
+        """Test WKT parsing of POINT geometries"""
+        wkt = "SRID=1;POINT(6554860 967048)"
+        self.assertPointListEquals(parse_wkt_thuban(wkt),
+                                   [[(6554860, 967048)]])
+
+    def test_multilinestring(self):
+        """Test WKT parsing of MULTILINESTRING geometries"""
+        wkt = ("MULTILINESTRING(("
+               "(6489598.51 867720.64,"
+               "6489593.90 867837.42),"
+               "(6489624.12 867714.83,"
+               "6489629.83 867621.31,"
+               "6489616.35 867552.57,"
+               "6489608.31 867507.10),"
+               "(6489902.89 868153.54,"
+               "6489880.85 868167.12,"
+               "6489837.96 868136.41,"
+               "6489788.94 868071.37)))")
+        self.assertPointListEquals(parse_wkt_thuban(wkt),
+                                  [[(6489598.51, 867720.64),
+                                    (6489593.90, 867837.42)],
+                                   [(6489624.12, 867714.83),
+                                    (6489629.83, 867621.31),
+                                    (6489616.35, 867552.57),
+                                    (6489608.31, 867507.10)],
+                                   [(6489902.89, 868153.54),
+                                    (6489880.85, 868167.12),
+                                    (6489837.96, 868136.41),
+                                    (6489788.94, 868071.37)]])
+
+    def test_polygon(self):
+        """Test WKT parsing of POLYGON geometries"""
+        wkt = ("SRID=1;POLYGON((6545639.323878 961209.599602,"
+               "6545630.08526 961213.426864,6545617.99819 961184.249912,"
+               "6545627.236809 961180.422651,6545639.323878 961209.599602))")
+        self.assertPointListEquals(parse_wkt_thuban(wkt),
+                                   [[(6545639.323878, 961209.599602),
+                                     (6545630.08526, 961213.426864),
+                                     (6545617.99819, 961184.249912),
+                                     (6545627.236809, 961180.422651),
+                                     (6545639.323878, 961209.599602)]])
+
+    def test_errors(self):
+        """Test WKT parsing error detection"""
+        # empty strings cause value errors
+        self.assertRaises(ValueError, parse_wkt_thuban, "")
+        # strings with only an SRID cause value errors
+        self.assertRaises(ValueError, parse_wkt_thuban, "SRID=1")
+
+        # Missing parentheses cause value errors
+        self.assertRaises(ValueError, parse_wkt_thuban, "POINT(10 20")
+
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_wxproj.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_wxproj.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_wxproj.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,77 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Test cases for wxproj"""
+
+__version__ = "$Revision: 1864 $"
+# $Source$
+# $Id: test_wxproj.py 1864 2003-10-24 17:25:53Z bh $
+
+import os
+import unittest
+
+import support
+support.initthuban()
+
+import shapelib
+from wxproj import shape_centroid
+from Thuban.Model.proj import Projection
+
+
+class TestShapeCentroid(unittest.TestCase, support.FloatComparisonMixin):
+
+    """Test cases for wxproj.shape_centroid()"""
+
+    def setUp(self):
+        filename = os.path.join("..", "Data", "iceland", "political.shp")
+        self.shapefile = shapelib.ShapeFile(filename)
+        self.map_proj = Projection(["proj=utm", "zone=26", "ellps=clrk66"])
+        self.layer_proj = Projection(["proj=latlong",
+                                      "to_meter=0.017453292519943295",
+                                      "ellps=clrk66"])
+
+    def test_no_proj(self):
+        """Test shape_centroid without any projections"""
+        self.assertFloatSeqEqual(shape_centroid(self.shapefile.cobject(), 0,
+                                                None, None,
+                                                1, 1, 0, 0),
+                                 (-22.5514848648, 64.7794567309))
+
+    def test_map_proj(self):
+        """Test shape_centroid with map projection"""
+        self.assertFloatSeqEqual(shape_centroid(self.shapefile.cobject(), 0,
+                                                self.map_proj, None,
+                                                1, 1, 0, 0),
+                                 (711378, 7191110),
+                                 epsilon = 1)
+
+    def test_layer_proj(self):
+        """Test shape_centroid with layer projection"""
+        self.assertFloatSeqEqual(shape_centroid(self.shapefile.cobject(), 0,
+                                                None, self.layer_proj,
+                                                1, 1, 0, 0),
+                                 (-22.5514848648, 64.7794567309))
+
+    def test_both_proj(self):
+        """Test shape_centroid with map and layer projection"""
+        self.assertFloatSeqEqual(shape_centroid(self.shapefile.cobject(), 0,
+                                                self.map_proj, self.layer_proj,
+                                                1, 1, 0, 0),
+                                 (711378, 7191110),
+                                 epsilon=1)
+
+    def test_invalid_shape_id(self):
+        """Test shape_centroid without an invalid shape id"""
+        self.assertRaises(ValueError, shape_centroid,
+                          self.shapefile.cobject(), -1, None, None,
+                          1, 1, 0, 0)
+        self.assertRaises(ValueError, shape_centroid,
+                          self.shapefile.cobject(), 1000000, None, None,
+                          1, 1, 0, 0)
+
+if __name__ == "__main__":
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/test_xmlsupport.py
===================================================================
--- packages/thuban/branches/upstream/current/test/test_xmlsupport.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/test_xmlsupport.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,103 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Test for the xmlsupport.py module
+"""
+
+__version__ = "$Revision: 1280 $"
+# $Source$
+# $Id: test_xmlsupport.py 1280 2003-06-20 18:29:16Z bh $
+
+import unittest
+
+import xmlsupport
+import support
+
+class TestValidation(unittest.TestCase, xmlsupport.ValidationTest):
+
+    def test_simple(self):
+        """test xmlsupport validating valid XML
+
+        The test succeeds if validate_data doesn't raise any exception
+        """
+        data = ('<?xml version="1.0" encoding="UTF-8"?>\n'
+                '<!DOCTYPE session SYSTEM "thuban.dtd">\n'
+                '<session title="empty session">\n</session>\n')
+        self.validate_data(data)
+
+    def test_invalid(self):
+        """test xmlsupport validating invalid XML
+
+        The test succeeds if validate_data raises an assertion error
+        """
+        data = ('<?xml version="1.0" encoding="UTF-8"?>\n'
+                '<!DOCTYPE session SYSTEM "thuban.dtd">\n'
+                '<session foo="bar">\n</session>\n')
+        # only really run this test when pyRXP is available
+        if xmlsupport.pyRXP is not None:
+            self.assertRaises(AssertionError, self.validate_data, data)
+
+
+
+class TestEventList(unittest.TestCase):
+
+    """Test cases for sax_eventlist"""
+
+    def test_even_list_simple(self):
+        """Test sax_eventlist on very simple XML"""
+        data = "\n".join(['<?xml version="1.0" encoding="UTF-8"?>'
+                          '<!DOCTYPE session SYSTEM "thuban.dtd">'
+                          '<session title="single map&amp;layer">'
+                          '</session>'])
+
+        self.assertEquals(xmlsupport.sax_eventlist(data = data),
+                          [('start', (None, u'session'),
+                            [((None, u'title'), u'single map&layer')]),
+                           ('end', (None, u'session'))])
+
+    def test_even_list_namespace(self):
+        """Test sax_eventlist on XML with a default namespace"""
+        data = "\n".join(['<?xml version="1.0" encoding="UTF-8"?>'
+                          '<!DOCTYPE session SYSTEM "thuban.dtd">'
+                          '<session title="single map&amp;layer"'
+                            ' xmlns="http://example.com/example.dtd">'
+                          '</session>'])
+
+        self.assertEquals(xmlsupport.sax_eventlist(data = data),
+                          [('start', (u'http://example.com/example.dtd',
+                                      u'session'),
+                            [((None, u'title'), u'single map&layer')]),
+                           ('end', (u'http://example.com/example.dtd',
+                                    u'session'))])
+
+    def test_even_list_id_normalization(self):
+        """Test sax_eventlist id normalization"""
+        data1 = "\n".join(['<?xml version="1.0" encoding="UTF-8"?>'
+                           '<!DOCTYPE session SYSTEM "thuban.dtd">'
+                           '<session title="bla">'
+                           '   <table id="foo"/>'
+                           '   <tableref id="foo"/>'
+                           '</session>'])
+
+        data2 = "\n".join(['<?xml version="1.0" encoding="UTF-8"?>'
+                           '<!DOCTYPE session SYSTEM "thuban.dtd">'
+                           '<session title="bla">'
+                           '   <table id="bar"/>'
+                           '   <tableref id="bar"/>'
+                           '</session>'])
+        ids = [((None, "table"), (None, "id"))]
+        idrefs = [((None, "tableref"), (None, "id"))]
+        self.assertEquals(xmlsupport.sax_eventlist(data = data1, ids = ids,
+                                                   idrefs = idrefs),
+                          xmlsupport.sax_eventlist(data = data2, ids = ids,
+                                                   idrefs = idrefs))
+
+if __name__ == "__main__":
+    # Fake the __file__ global because it's needed by a test
+    import sys
+    __file__ = sys.argv[0]
+    support.run_tests()

Added: packages/thuban/branches/upstream/current/test/xmlsupport.py
===================================================================
--- packages/thuban/branches/upstream/current/test/xmlsupport.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/test/xmlsupport.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,171 @@
+# Copyright (C) 2003 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""XML support code for the test cases"""
+
+__version__ = "$Revision: 1683 $"
+# $Source$
+# $Id: xmlsupport.py 1683 2003-08-28 15:20:57Z bh $
+
+import sys
+import os
+from StringIO import StringIO
+import xml.sax
+import xml.sax.handler
+from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException
+
+import support
+
+try:
+    import pyRXP
+except ImportError:
+    pyRXP = None
+
+class ValidationTest:
+
+    """Mix-in class for tests that want to check for validity of XML data"""
+
+    # If true, at least one test case tried to validate XML data but
+    # couldn't because PyRXP is not available
+    validation_attempt_ignored = False
+
+    def validate_data(self, data):
+        """Validate the XML data"""
+        if pyRXP is not None:
+            parser = pyRXP.Parser()
+            try:
+                parser.parse(data, eoCB = self.rxp_eo_cb)
+            except pyRXP.error, val:
+                raise AssertionError, str(val), sys.exc_info()[2]
+        else:
+            ValidationTest.validation_attempt_ignored = True
+
+    def rxp_eo_cb(self, filename):
+        """Resolve an eternal entity
+
+        In the Thuban test cases the only external entities that have to
+        be resolved are the DTDs which now live in the resource
+        directory. So, interpret any filename relative to that
+        directory.
+        """
+        return os.path.join(support.resource_dir(), "XML", filename)
+
+
+#
+# Classes and functions to convert XML to a normalized list
+# representation for comparisons
+#
+
+class SaxEventLister(xml.sax.handler.ContentHandler):
+
+    """Create a normalized list representation containing the SAX events
+
+    The normalization includes the following
+
+     - The attribute dictionary of a staertElement event is converted to
+       a sorted list of (key, value) pairs
+
+     - ID and IDREF attribute values are normalized in such a way that
+       two documents that only use different values for IDs can still
+       lead to the same normalized representation.
+
+       The implementation of this feature assumes that all IDs are
+       defined before they are used. The normalized ID values are of the
+       form 'D<NUM>' where <NUM> is a counter starting with 0, so the
+       first ID value will become 'D0', the second 'D1', etc.
+
+       Which attributes are IDs or IDREFS is defined with the
+       correspoding constructor arguments.
+
+     - Filenames are normalized with os.path.normpath. Which attributes
+       are filenames is defiend with the corresponding constructor
+       argument.
+    """
+
+    def __init__(self, ids = (), idrefs = (), filenames = ()):
+        """Initialize the SaxEventLister
+
+        The ids and idrefs parameters should be lists of (element, attr)
+        pairs where element is the name of an attribute as passed to the
+        startElementNS method and attr is the name of an attribute as
+        used in the mapping passed to startElementNS, so both name and
+        attr usually must include the namespace.
+
+        The filenames parameter should be a sequence of the same form as
+        ids and idrefs identifying the attributes which are filenames
+        that should be normalized.
+        """
+        self.eventlist = []
+        self.ids = ids
+        self.idrefs = idrefs
+        self.idremap = {}
+        self.filenames = filenames
+
+    def startElementNS(self, name, qname, attrs):
+        items = attrs.items()
+        items.sort()
+        for i, (attr, value) in zip(range(len(items)), items):
+            #print '++++'
+            #print self.idremap
+            #print name, attr, value
+            if (name, attr) in self.ids:
+                newid = len(self.idremap)
+                self.idremap[value] = "D" + str(newid)
+                value = self.idremap[value]
+            elif (name, attr) in self.idrefs:
+                value = self.idremap[value]
+            elif (name, attr) in self.filenames:
+                value = os.path.normpath(value)
+            items[i] = (attr, value)
+            #print name, attr, value
+        self.eventlist.append(("start", name, items))
+
+    def endElementNS(self, name, qname):
+        self.eventlist.append(("end", name))
+
+
+def sax_eventlist(data = None, filename = None,
+                  ids = (), idrefs = (), filenames = ()):
+    """Return a list of SAX event generated for a given XML source
+
+    The xml source may either be a string with the actual XML, in which
+    case it should be given as the keyword argument data or the name of
+    an xml file given as the keyword argument filename
+    """
+    if filename is not None:
+        data = open(filename).read()
+    handler = SaxEventLister(ids = ids, idrefs = idrefs, filenames = filenames)
+    parser = make_parser()
+    parser.setContentHandler(handler)
+    parser.setErrorHandler(ErrorHandler())
+    parser.setFeature(xml.sax.handler.feature_namespaces, 1)
+
+    #
+    # see comment at the end of Thuban/Model/load.py
+    #
+    try:
+        parser.setFeature(xml.sax.handler.feature_validation, 0)
+        parser.setFeature(xml.sax.handler.feature_external_ges, 0)
+        parser.setFeature(xml.sax.handler.feature_external_pes, 0)
+    except SAXNotRecognizedException:
+        pass
+
+    inpsrc = xml.sax.InputSource()
+    inpsrc.setByteStream(StringIO(data))
+    parser.parse(inpsrc)
+
+    return handler.eventlist
+
+
+def print_summary_message():
+    """Print a summary message about validation tests
+
+    Currently simply print a message about pyRXP not being available if
+    a test case's attempt to validate XML was ignored because of that.
+    """
+    if ValidationTest.validation_attempt_ignored:
+        print "XML validation attempts ignored because pyRXP is not available"

Added: packages/thuban/branches/upstream/current/thuban.py
===================================================================
--- packages/thuban/branches/upstream/current/thuban.py	2007-04-06 11:24:19 UTC (rev 717)
+++ packages/thuban/branches/upstream/current/thuban.py	2007-04-06 11:44:54 UTC (rev 718)
@@ -0,0 +1,37 @@
+#! /usr/bin/python
+
+# Copyright (c) 2001 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh at intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+import sys, os
+import Thuban
+
+# Put the Lib dir into the path. The Lib dir contains some extra non
+# really Thuban specific Python modules
+thubandir = os.path.join(Thuban.__path__[0], '..')
+dir = os.path.join(thubandir, "Lib")
+if os.path.isdir(dir):
+    sys.path.insert(0, dir)
+
+# win32 gdal support
+if sys.platform == 'win32':
+    # PYTHONPATH update
+    dir = os.path.join(thubandir, "gdal", "pymod")
+    if os.path.isdir(dir):
+        sys.path.append(dir)
+
+    try:
+        import gdal
+    except ImportError:
+        print "Please update your PATH environment variable to include %s\\gdal\\bin" % thubandir
+
+import Thuban.UI.main
+    
+# Start Thuban
+Thuban.UI.main.main()
+
+


Property changes on: packages/thuban/branches/upstream/current/thuban.py
___________________________________________________________________
Name: svn:executable
   + 




More information about the Pkg-grass-devel mailing list